📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 147편
이전 글: 146. 비정상 TCP Traffic 분석 · 다음 글: 148. pcap 증거 보존과 해시 검증
외부 비정상 통신은 내부 자산이 업무와 맞지 않는 외부 목적지와, 평소와 다른 방식으로 통신하는 것입니다. 443 같은 정상 포트로 위장하는 이유, 비커닝과 TLS 지문(JA3/JA4)의 개념은 90. 정상 포트로 위장한 통신 — 443을 쓰는 비정상 트래픽에서, DNS를 통한 비정상 통신은 144. DNS 악용 유형 — 터널링·DGA·비정상 질의 탐지에서 다뤘습니다. 이 글은 pcap 하나에서 외부 통신을 골라 단서를 찾는 Wireshark 절차를 다룹니다.
| 단서 | 패킷에서 보는 필드·기능 |
|---|---|
| 바이트 방향 | Conversations의 A→B / B→A 바이트 |
| 연결 주기 | 같은 목적지로 가는 SYN의 시간 간격 |
| 포트와 프로토콜 불일치 | 포트 번호 vs Wireshark가 해석한 프로토콜 |
| IP 직접 접속 | http.host, tls.handshake.extensions_server_name 유무 |
| 외부 DNS 직접 사용 | dns 목적지가 내부 리졸버가 아님 |
| 비정상 ICMP | 큰 데이터, 요청마다 다른 내용 (118. Ping Packet 분석) |
전체 캡처
↓ ① 내부 → 외부만 남기기
ip.src == 192.168.10.0/24 && !(ip.dst == 192.168.10.0/24)
↓ ② Statistics → Conversations (IPv4, Name resolution 끔)
바이트 큰 순 / 지속 시간 긴 순 / 연결 수 많은 순으로 정렬
↓ ③ 상위 목적지 하나씩 : 프로토콜·포트·SNI·Host 확인
↓ ④ 같은 목적지로 가는 연결 시각 간격 계산 (주기성)
↓ ⑤ 판단 근거 기록 → IOC 추출(149편) · 사고 분석(150편)
!(ip.dst == 10.0.0.0/8 or ip.dst == 172.16.0.0/12 or ip.dst == 192.168.0.0/16)처럼 확장합니다.ip.geoip.* 필드로 볼 수 있습니다(DB는 별도 준비).불일치·우회 단서 필터
| 확인 대상 | Display Filter |
|---|---|
| 443이 아닌 포트의 TLS | tls.handshake.type == 1 && tcp.dstport != 443 |
| 80·8080이 아닌 포트의 HTTP 요청 | http.request && !(tcp.dstport in {80 8080}) |
| 표준 포트인데 해석이 안 되는 데이터 | tcp.dstport == 443 && tcp.len > 0 && !tls |
| SNI 없는 TLS 연결 | tls.handshake.type == 1 && !tls.handshake.extensions_server_name |
| Host에 IP를 직접 쓴 HTTP | http.host matches "^[0-9.]+(:[0-9]+)?$" |
| 내부 리졸버가 아닌 DNS | dns.flags.response == 0 && ip.dst != 192.168.10.1 |
Conversations에서 읽는 형태 (추정이며 확정이 아님)
| 형태 | 가능한 해석 |
|---|---|
| 내부 → 외부 바이트가 외부 → 내부보다 훨씬 큼 | 업로드(백업·동기화 또는 유출) |
| 작은 연결이 일정 간격으로 수십~수백 회 | 주기적 체크인(업데이트 확인 또는 비커닝) |
| 한 연결이 수 시간 유지, 트래픽 드묾 | 원격 제어·터널 가능성 |
| 목적지가 이 캡처에서만 보이는 드문 주소 | 새로운 목적지 → 평판 확인 대상 |
분석 방법 예시 — 확보한 캡처에서 외부 목적지를 정리하고 주기성을 계산합니다. 명령과 출력은 예시(값은 환경마다 다름)이며, 외부 주소는 문서용 대역으로 표기합니다.
# 1) 외부 목적지별 대화 요약 (바이트 큰 순은 GUI 정렬 또는 출력 확인)
tshark -r case.pcapng -q -z conv,ip,'ip.src == 192.168.10.0/24 && !(ip.dst == 192.168.10.0/24)'
# 2) 특정 목적지로 가는 새 연결(SYN) 시각과 직전 연결과의 간격(초)
tshark -r case.pcapng -Y 'ip.dst == 203.0.113.50 && tcp.flags.syn == 1 && tcp.flags.ack == 0' \
-T fields -e frame.time_epoch \
| awk 'NR>1 {printf "%.1f\n", $1-prev} {prev=$1}' | sort -n | uniq -c
# 3) 외부 TLS 연결의 목적지·포트·SNI
tshark -r case.pcapng -Y 'tls.handshake.type == 1 && !(ip.dst == 192.168.10.0/24)' \
-T fields -e ip.dst -e tcp.dstport -e tls.handshake.extensions_server_name | sort | uniq -c
2)번 결과의 형식 예시입니다.
1 59.8
38 60.0 ← 대부분 약 60초 간격
2 60.3
1 312.4 ← 중간에 한 번 긴 공백
간격이 거의 일정하면 자동화된 통신입니다. 이것이 정상 소프트웨어의 업데이트 확인인지, 알 수 없는 프로세스의 체크인인지는 패킷만으로 결론 내리지 않고, 목적지 평판·SNI·해당 단말의 프로세스 정보를 함께 확인합니다(90. 정상 포트로 위장한 통신 — 443을 쓰는 비정상 트래픽의 호스트 확인 절차).
📷 [실습 화면 삽입 위치] 내부 → 외부 필터를 적용한 Conversations(IPv4) 창을 Bytes A→B 기준으로 정렬한 화면
📷 [실습 화면 삽입 위치] 특정 외부 목적지 SYN에
frame.time_delta_displayed열을 추가해 일정한 간격이 보이는 Packet List
| 관찰 | 정상일 수 있는 경우 | 추가 확인이 필요한 경우 |
|---|---|---|
| 일정 간격 외부 연결 | OS·백신 업데이트, 메신저, 모니터링 에이전트 | 알려지지 않은 목적지, 업무 외 시간 지속 |
| 대용량 업로드 | 클라우드 백업·동기화 | 평소 업로드가 없는 단말, 개인 저장소 목적지 |
| 비표준 포트 TLS | 사내 서비스, VPN | 처음 보는 외부 주소 |
| IP 직접 HTTP 접속 | 장비 관리 페이지, 일부 CDN | 실행 파일 다운로드가 이어짐 |
| 외부 DNS 직접 질의 | 개발자 단말 설정 | 내부 리졸버 우회 정책 위반 |
| 흔적 위치 | 확인할 수 있는 것 |
|---|---|
| 패킷 캡처 | 방향별 바이트, 주기, 프로토콜·SNI·Host, 데이터 내용(평문일 때) |
| 방화벽·프록시 로그 | 목적지·포트·허용 여부, URL(프록시) |
| DNS 로그 | 해당 목적지를 조회한 단말과 시각 |
| EDR·호스트 로그 | 연결을 만든 프로세스 (패킷으로는 확인 불가) |
관제자가 확인할 질문
오탐 주의: CDN·클라우드 주소는 여러 서비스가 공유하므로 IP 하나로 판단하지 않습니다. 정상 에이전트의 주기 통신이 가장 흔한 오탐 원인이므로 자산별 허용 목적지 목록을 먼저 대조합니다.