📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 139편
이전 글: 138. HTTPS Traffic 이해 · 다음 글: 140. SSH Traffic 이해
FTP가 제어 연결(TCP 21)과 데이터 연결을 나누는 구조, Active·Passive 모드의 방향, 서버 로그(vsftpd)로 추적하는 방법은 63. FTP Active·Passive 모드와 보안에서 다뤘습니다. 이 글은 Wireshark 화면에서 FTP 세션 하나를 처음부터 끝까지 읽는 방법만 다룹니다.
| 구분 | Wireshark 프로토콜 이름 | 담기는 내용 |
|---|---|---|
| 제어 연결 | ftp | 명령(USER, PASS, PASV, RETR 등)과 3자리 응답 코드, 평문 |
| 데이터 연결 | ftp-data | 파일 내용, 디렉터리 목록(LIST 결과) |
| 암호화 제어 연결 | ftp 이후 tls | AUTH TLS 이후 명령이 보이지 않음 (FTPS, RFC 4217) |
Wireshark는 제어 연결에서 본 227(PASV) 또는 PORT 명령의 주소·포트를 기억했다가, 그 주소·포트로 생기는 TCP 연결을 ftp-data로 해석합니다.
[제어 연결 tcp.stream 0 : 192.168.10.20:51000 → 192.168.10.30:21]
220 Service ready
USER alice → 331 Password required
PASS ******** → 230 Login successful
PASV → 227 Entering Passive Mode (192,168,10,30,156,65)
↓ 포트 = 156 × 256 + 65 = 40001
[데이터 연결 tcp.stream 1 : 192.168.10.20:51002 → 192.168.10.30:40001] ← ftp-data
RETR report.txt → 150 Opening data connection
↓ (stream 1에서 파일 내용 전송 후 종료)
→ 226 Transfer complete
QUIT → 221 Goodbye
ftp-data로 알아보지 못하고 일반 TCP로 표시합니다. 이때는 Decode As로 직접 지정해야 합니다.EPSV(응답 229), EPRT(RFC 2428)가 쓰이며, 이 경우 응답에 IP 없이 포트만 들어갑니다.자주 쓰는 FTP 필드 (버전에 따라 이름이 다를 수 있으므로 Details에서 우클릭 → Copy → Field Name으로 확인)
| 필드 | 의미 | 필터 예 |
|---|---|---|
ftp.request.command | 클라이언트 명령 | ftp.request.command == "RETR" |
ftp.request.arg | 명령 인자 (계정명, 파일명 등) | ftp.request.arg contains ".php" |
ftp.response.code | 서버 응답 코드 | ftp.response.code == 530 |
ftp.passive.ip / ftp.passive.port | 227 응답에 담긴 데이터 주소·포트 | ftp.passive.port |
ftp.active.cip / ftp.active.port | PORT 명령에 담긴 주소·포트 | ftp.active.cip != ip.src |
ftp-data.command | 이 데이터 연결을 만든 명령 (Wireshark가 연결) | ftp-data.command contains "STOR" |
세션 재구성에 쓰는 응답 코드 (RFC 959)
| 코드 | 의미 | 분석에서의 역할 |
|---|---|---|
| 220 / 221 | 서비스 준비 / 종료 | 세션 시작·끝 표시, 220 배너에 서버 소프트웨어가 보이기도 함 |
| 331 → 230 | 비밀번호 요구 → 로그인 성공 | 인증 성공 시점 |
| 530 | 로그인 실패 | 실패 횟수 집계 대상 |
| 227 / 229 | Passive / Extended Passive 진입 | 데이터 연결 포트 확인 |
| 150 → 226 | 데이터 연결 열림 → 전송 완료 | 파일 전송 1건의 시작·끝 |
| 425 / 550 | 데이터 연결 실패 / 파일 없음·권한 없음 | 실패한 시도 식별 |
실습 예시 — 본인 소유 실습망의 FTP 서버에 접속하는 트래픽을 캡처해 분석합니다. 명령과 출력은 예시(값은 환경마다 다름)입니다. 서버 설치는 63. FTP Active·Passive 모드와 보안의 Rocky/Ubuntu 절차를 따릅니다.
# 캡처 (Rocky/Ubuntu 공통, 제어+데이터 연결을 모두 담기 위해 호스트 기준 필터)
sudo tcpdump -i ens33 -nn -w /tmp/ftp.pcapng 'host 192.168.10.30'
# 1) 제어 연결의 명령·응답 흐름을 시간순으로
tshark -r /tmp/ftp.pcapng -Y 'ftp' -T fields -E header=y \
-e frame.number -e tcp.stream -e ftp.request.command -e ftp.request.arg \
-e ftp.response.code -e ftp.response.arg
# 2) 데이터 연결과 그 연결을 만든 명령
tshark -r /tmp/ftp.pcapng -Y 'ftp-data' -T fields \
-e tcp.stream -e tcp.dstport -e ftp-data.command | sort -u
# 3) 데이터 연결에서 전송된 파일을 추출 (Wireshark GUI와 같은 기능)
mkdir -p /tmp/ftp_obj
tshark -r /tmp/ftp.pcapng --export-objects ftp-data,/tmp/ftp_obj
sha256sum /tmp/ftp_obj/*
1)번 결과의 형식 예시입니다.
frame.number tcp.stream ftp.request.command ftp.request.arg ftp.response.code ftp.response.arg
4 0 220 (vsFTPd x.x.x)
6 0 USER alice
8 0 331 Please specify the password.
10 0 PASS (평문 비밀번호)
12 0 230 Login successful.
14 0 PASV
15 0 227 Entering Passive Mode (192,168,10,30,156,65).
17 0 RETR report.txt
GUI에서는 Tools → Credentials(최신 버전) 메뉴가 FTP의 USER/PASS를 목록으로 보여 주고, File → Export Objects → FTP-DATA가 전송된 파일을 보여 줍니다. 제어 연결은 Follow TCP Stream으로 대화처럼 읽을 수 있습니다(134. Follow TCP Stream).
📷 [실습 화면 삽입 위치] 필터
ftp에ftp.request.command,ftp.response.code열을 추가해 로그인부터 226까지 흐름이 보이는 Packet List
📷 [실습 화면 삽입 위치] File → Export Objects → FTP-DATA 창에 전송 파일 이름과 크기가 표시된 화면
| 패킷에서 보이는 것 | 정상일 수 있는 경우 | 추가 확인이 필요한 경우 |
|---|---|---|
PASS 인자가 평문으로 보임 | 레거시 내부 시스템 | 외부 구간을 지나는 평문 FTP (계정 노출) |
짧은 시간 530 반복 | 비밀번호 오입력 몇 회 | 다수 계정·다수 시도 (무차별 대입, 05 영역에서 다룸) |
STOR 명령 + 웹 스크립트 확장자 | 콘텐츠 배포 | FTP 루트가 웹 루트와 같은 서버에 스크립트 업로드 |
ftp.active.cip가 제어 연결 출발지와 다름 | NAT 설정 오류 | 제3의 주소를 지정하는 FTP Bounce 형태 |
내부 → 외부 STOR 대용량 | 승인된 파일 교환 | 미승인 목적지로 업로드 (유출 의심, 147. 외부 비정상 통신 분석) |
평문 FTP 캡처는 계정 정보를 그대로 담고 있으므로 pcap 자체를 민감 자료로 다루고, 보관·공유 시 148. pcap 증거 보존과 해시 검증의 증거 관리 절차를 따릅니다.
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 패킷 캡처 | 명령·응답 전체, 계정명, 전송 파일 이름과 내용 |
| FTP 서버 로그 | 로그인 성공·실패, 업로드·다운로드 파일 (서버 기준) |
| 방화벽 로그 | 21번과 데이터 포트 범위 허용·차단, 세션 바이트 |
| IDS/IPS | 평문 로그인, 로그인 실패 반복, 의심 파일 전송 이벤트 |
관제자가 확인할 질문
230 로그인 성공 이후 어떤 명령(RETR, STOR, DELE, LIST)이 이어졌는가?150과 226 사이의 데이터 연결에서 실제로 전송된 바이트는 얼마인가?ftp-data 연결 수가 일치하는가?오탐 주의: 데이터 연결이 FTP로 해석되지 않는다고 "FTP 없이 이상한 포트로 대량 전송"으로 판단하면 안 됩니다. 캡처 시작 시점과 제어 연결 존재 여부를 먼저 확인합니다. FTPS는 AUTH TLS 이후 명령이 보이지 않는 것이 정상입니다.
ftp와 데이터 연결 ftp-data로 나뉘어 보입니다.227/229 응답이나 PORT 명령의 주소·포트를 근거로 Wireshark가 데이터 연결을 ftp-data로 연결하므로, 제어 연결이 캡처에 있어야 합니다.ftp.request.command와 ftp.response.code만으로 로그인(331→230/530)과 파일 전송(150→226) 흐름을 재구성할 수 있습니다.