📚 네트워크 · 패킷 분석 › 01. TCP/IP 구조 이해 — 50편
이전 글: 49. 사설 IP · 공인 IP와 NAT — 로그의 IP가 서로 다른 이유 · 다음 글: 51. 포트 번호 체계 — Well-known·Registered·임시 포트
참고(리눅스 시스템 기초): Socket 이해 — 애플리케이션이 소켓으로 통신을 요청하는 구조
관제에서 하나의 이벤트를 분석할 때도 마찬가지입니다. "사용자 PC가 외부 사이트에 접속했다"는 한 문장 뒤에는 DNS 질의, ARP, 라우팅, NAT 변환, TCP 연결, HTTP 요청이 있고, 각 단계는 서로 다른 장비와 로그에 흔적을 남깁니다. 어느 단계의 증거가 어디에 있는지 알아야 여러 로그를 시간 순으로 엮어 하나의 사건으로 재구성할 수 있습니다.
이 글은 새로운 개념을 추가하지 않고, 01 시리즈 전체를 "웹 요청 하나의 타임라인"과 "단계별 증거 맵" 으로 묶어 정리합니다.
| 항목 | 값 (예시) |
|---|---|
| 클라이언트 | 192.168.10.20/24, 인터페이스 ens33 |
| 기본 게이트웨이 | 192.168.10.1 |
| 사내 DNS 리졸버 | 192.168.10.53 |
| 방화벽 NAT 공인 IP | 198.51.100.7 |
| 웹 서버 | www.example.com → 203.0.113.80, TCP 80 |
| 요청 | http://www.example.com/index.html |
설명을 단순하게 하려고 평문 HTTP(80)를 기준으로 하고, HTTPS는 달라지는 지점만 짚습니다.
| 단계 | 일어나는 일 | 관련 글 |
|---|---|---|
| 0 | URL 해석, 계층별 캡슐화 준비 | 01. OSI 7계층과 TCP/IP 4계층 |
| 1 | 도메인 → IP 이름 해석 | 14. DNS 이름 해석 흐름 |
| 2 | 목적지가 같은 서브넷인지 판단 | 03. IPv4 주소와 서브넷(CIDR) |
| 3 | 게이트웨이로 보내기로 결정 | 04. 게이트웨이와 라우팅 기초 |
| 4 | 게이트웨이 MAC 확인 | 02. Ethernet 프레임과 MAC 주소 · ARP |
| 5 | 경계에서 사설 → 공인 주소 변환 | 05. 사설 IP · 공인 IP와 NAT |
| 6 | TCP 연결 수립 | 07. TCP와 UDP 헤더, 08. TCP 3-Way Handshake |
| 7 | HTTP 요청·응답 데이터 전달 | 11. 시퀀스 번호·ACK·윈도우, 12. MTU와 IP 단편화 |
| 8 | 연결 종료와 상태 정리 | 09. TCP 연결 종료, 10. TCP 상태 전이 |
| 예외 | 경로 오류·도달 불가 통보 | 06. ICMP와 ping |
| 변형 | DNS가 AAAA를 돌려주면 IPv6 경로 사용 | 13. IPv6 기초 |

그림 1. 한 번의 웹 요청이 거치는 단계와 각 단계에서 확인할 수 있는 증거
[0] 브라우저: http://www.example.com/index.html
→ 스킴 http, 호스트 www.example.com, 포트 80(기본), 경로 /index.html
↓
[1] 이름 해석: /etc/hosts → 로컬 캐시 → 리졸버 192.168.10.53 (UDP 53)
→ A 203.0.113.80 (AAAA도 함께 질의될 수 있음)
↓
[2] 서브넷 판단: 203.0.113.80 은 192.168.10.0/24 밖 → 직접 전달 불가
↓
[3] 라우팅: 라우팅 테이블 default via 192.168.10.1 선택
↓
[4] ARP: "192.168.10.1 의 MAC?" → 캐시에 없으면 브로드캐스트 요청
→ 프레임 목적지 MAC = 게이트웨이 MAC, IP 목적지 = 203.0.113.80 (IP는 그대로)
↓
[5] 경계 방화벽: 정책 허용 확인 → SNAT 192.168.10.20:51544 → 198.51.100.7:40123
→ 라우터마다 TTL 1 감소, 구간마다 MAC 교체
↓
[6] TCP Handshake: SYN → SYN/ACK → ACK (MSS·Window Scale·SACK 협상)
↓
[7] HTTP: GET /index.html (seq 전진) → 서버 응답 200 + 본문 (여러 세그먼트, ACK 누적)
↓ ※ HTTPS라면 [6] 이후 TLS Handshake가 먼저, [7] 내용은 암호화
[8] 종료: FIN/ACK 교환 → 먼저 닫은 쪽 TIME_WAIT, 또는 RST로 즉시 종료
→ 방화벽 세션 테이블 항목 삭제, 세션 로그(바이트·지속 시간) 기록
단계별로 짚을 점은 다음과 같습니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu), 인터페이스 이름은 ens33 예시입니다. 대상은 예시용으로 예약된 도메인 example.com을 사용합니다.
# Rocky Linux
sudo dnf install -y curl tcpdump bind-utils iproute
# Ubuntu
sudo apt update && sudo apt install -y curl tcpdump dnsutils iproute2
ip -4 addr show dev ens33 # [2] 내 주소·서브넷
ip route get 203.0.113.80 # [3] 이 목적지는 어느 게이트웨이로? (실습 시 실제 IP로)
ip neigh show dev ens33 # [4] 현재 ARP 캐시
grep '^hosts' /etc/nsswitch.conf # [1] 조회 순서
# 터미널 1: ARP·DNS·HTTP를 한 파일로 캡처
sudo tcpdump -i ens33 -nn -w web_path.pcap 'arp or port 53 or port 80'
# 터미널 2: 처음부터 보이도록 캐시를 비운 뒤 요청 (본인 VM에서만)
sudo ip neigh flush dev ens33 # ARP 캐시 비우기 → [4] 재발생
sudo resolvectl flush-caches 2>/dev/null # Ubuntu 로컬 DNS 캐시 비우기
curl -s -o /dev/null http://www.example.com/
ip neigh flush는 잠깐 동안 SSH 등 기존 연결에 지연을 줄 수 있으니 콘솔에서 실행하는 것이 안전합니다.
curl -w의 시간 변수는 단계 경계와 그대로 대응됩니다.
curl -s -o /dev/null -w \
'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' \
http://www.example.com/
# HTTPS와 비교 (tls 값이 0이 아니게 됨)
curl -s -o /dev/null -w \
'dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\n' \
https://www.example.com/
sudo tcpdump -nn -e -r web_path.pcap arp # [4]
sudo tcpdump -nn -r web_path.pcap port 53 # [1]
sudo tcpdump -nn -r web_path.pcap 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0' # [6][8]
sudo tcpdump -nn -A -r web_path.pcap 'tcp port 80 and tcp[tcpflags] & tcp-push != 0' | head -40 # [7]
# 종료 후 클라이언트 쪽 TIME_WAIT 확인 [8]
ss -tan state time-wait '( dport = :80 )'
📷 [실습 화면 삽입] tcpdump로 읽은 web_path.pcap — ARP 요청/응답, DNS 질의/응답, SYN·SYN/ACK·ACK, GET, FIN이 시간 순으로 이어지는 구간
📷 [실습 화면 삽입] Wireshark
Statistics > Flow Graph로 본 동일 pcap 흐름 — 단계 번호를 주석으로 표시
curl -w 출력 형식 예시(값은 환경마다 다름, 단위 초, 각 값은 요청 시작부터의 누적 시간):
dns:0.004 connect:0.041 tls:0.000 ttfb:0.083 total:0.084
dns:0.001 connect:0.038 tls:0.112 ttfb:0.151 total:0.152
| curl 값 | 끝난 단계 | 해석 포인트 |
|---|---|---|
time_namelookup | [1] 이름 해석 | 두 번째 요청에서 짧아지면 캐시 효과 |
time_connect | [6] TCP Handshake | connect - dns ≒ 서버까지 왕복 시간 |
time_appconnect | TLS Handshake | HTTP에서는 0 |
time_starttransfer | [7] 첫 응답 바이트 | 서버 처리 시간 포함 |
time_total | 전체 |
tcpdump 요약 형식 예시(값은 환경마다 다름):
ARP, Request who-has 192.168.10.1 tell 192.168.10.20, length 28
ARP, Reply 192.168.10.1 is-at 00:50:56:aa:bb:01, length 46
192.168.10.20.40331 > 192.168.10.53.53: 30211+ A? www.example.com. (33)
192.168.10.53.53 > 192.168.10.20.40331: 30211 1/0/1 A 203.0.113.80 (60)
192.168.10.20.51544 > 203.0.113.80.80: Flags [S], seq 2854113921, win 64240, options [mss 1460,...]
203.0.113.80.80 > 192.168.10.20.51544: Flags [S.], seq 1703928410, ack 2854113922, win 65160, ...
192.168.10.20.51544 > 203.0.113.80.80: Flags [P.], seq 1:80, ack 1, length 79: HTTP: GET / HTTP/1.1
192.168.10.20.51544 > 203.0.113.80.80: Flags [F.], seq 80, ack 1394, length 0
curl -w 값으로 단계별 소요 시간을 설명할 수 있다| 단계 | 패킷(클라이언트 쪽 캡처) | 호스트 증거 | 네트워크·보안 장비 로그 |
|---|---|---|---|
| [1] DNS | udp.port == 53 질의/응답 | hosts·resolv.conf, 로컬 캐시 | 리졸버 질의 로그, NSM DNS 로그 |
| [2]~[3] 라우팅 결정 | (직접 흔적 없음, 목적지 MAC으로 간접 확인) | ip route | — |
| [4] ARP | arp 요청/응답 | ip neigh | 스위치 MAC 테이블, (설정 시) ARP 감시 로그 |
| [5] NAT·정책 | 내부 캡처에는 변환 전 주소만 | — | 방화벽 허용/차단 로그, NAT 변환 로그 |
| [6] TCP 연결 | SYN·SYN/ACK·ACK | ss -tan ESTAB | 방화벽 세션 시작, IDS 플로우 기록 |
| [7] HTTP | 요청 라인·헤더(평문일 때) | 브라우저·애플리케이션 로그 | 프록시 로그, 웹 서버 access log, IDS/WAF 이벤트 |
| [8] 종료 | FIN 또는 RST | ss TIME_WAIT | 방화벽 세션 종료(바이트 수·지속 시간·종료 사유) |
| 예외 | ICMP 오류 | — | 라우터·방화벽 ICMP 로그 |
| 관찰된 마지막 단계 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| DNS 질의만 있고 연결 없음 | prefetch, 사용자가 접속 취소 | 차단된 도메인 질의 → 그 단말의 다른 활동 확인 |
| DNS 없이 바로 SYN | IP 직접 접속, 캐시·hosts 사용 | 외부 IP로 DNS 없이 반복 연결 → 하드코딩된 목적지 여부 확인 |
| SYN 반복 후 종료 | 서버 다운, 경로 장애 | 방화벽 차단(로그 확인), 다수 목적지로 SYN만 발생 → 05. 네트워크 스캔 · 공격 징후 분석 시리즈에서 다룸 |
| Handshake 후 즉시 RST | 서비스 거부 설정, 포트 닫힘 | IPS 차단 응답 여부 확인(06. 방화벽 · IDS/IPS 분석 시리즈에서 다룸) |
| 큰 응답만 멈춤 | — | PMTUD 블랙홀, 중간 장비 드롭 |
| 정상 완료, 응답 바이트가 요청 대비 매우 큼/작음 | 파일 다운로드, 캐시 응답 | 업로드 방향 바이트가 비정상적으로 큼 → 유출 여부를 프록시·세션 로그로 확인 |
# 한 pcap에서 대화(세션)별 요약: 어느 단계까지 갔는지 빠르게 파악
tshark -r web_path.pcap -q -z conv,tcp
tshark -r web_path.pcap -q -z conv,udp
여러 로그를 하나의 사건으로 엮는 기준
단계별로 넘기는 주제
한계와 오탐 주의