TCP 패킷 디버깅
1. SYN 없이 ACK만 보이는 이유
캡처 시작 전에 이미 연결이 맺어진 상태라서그렇다.
Wireshark 켰을 때 세션이 살아있으면 3-way handshake는 이미 끝난 거고 중간부터 잡히는 것.
BPF 필터로 연결 과정만 골라서 캡처할 수 있음.
# SYN만
tcpdump -i eth0 'tcp[13] = 2'
# SYN-ACK만
tcpdump -i eth0 'tcp[13] = 18'
# 둘 다 (3-way handshake 전체)
tcpdump -i eth0 'tcp[13] = 2 or tcp[13] = 18'
tcp[13]이 TCP 헤더에서 플래그 필드 위치고, SYN=2, SYN+ACK=18 이렇게 값이 나온다.
2. Seq랑 Ack가 뭔지
Seq = 내가 보내는 데이터가 전체 스트림에서 몇 번째 바이트부터인지
Ack = 상대방 데이터 중 다음에 받고 싶은 번호 (여기까지 잘 받았다는 뜻)
이 둘이 항상 이 등식을 만족해야 정상
상대 Seq + Len = 내 Ack
예를 들어 서버가 Seq=5906, Len=481 보내면 클라이언트 ACK는 Ack=6387 (5906+481) 이렇게 와야 함.
오늘 #79 → #80에서 정확히 이게 맞아떨어진 거 확인
3. SYN이랑 ACK 구분
- SYN → 연결 시작할 때만 쓰는 1회용. 3-way handshake에서만 나옴
- ACK → 연결 내내 클라이언트/서버 양쪽 다 계속 씀. 데이터 받을 때마다 붙음
4. HTTPS랑 TLS
포트 80은 HTTP 평문이라 Wireshark에서 내용 바로 보임. 포트 443은 TCP 위에 TLS가 HTTP를 암호화한 거라 Application Data로만 표시됨.
IP → TCP → TLS → HTTP (실제 내용)
Wireshark는 TLS까지밖에 못 봐서 안에 HTTP가 있는지는 추론임. 포트 443이고 요청/응답 패턴이 반복되면 HTTPS라고 봐도 됨.
내용 보려면 클라이언트에서 세션 키 뽑아야 함.
export SSLKEYLOGFILE=~/tls_keys.log
# Wireshark → Preferences → TLS → 키 파일 지정
TLS Handshake 순서 (1.2 기준)
- ClientHello → 지원하는 암호화 방식 목록이랑 랜덤값 전송
- ServerHello + Certificate → 서버가 암호화 방식 골라서 인증서랑 같이 응답
- ClientKeyExchange → Pre-Master Secret을 서버 공개키로 암호화해서 전달
- 양쪽이 각자 Master Secret 계산 → 세션 키 파생 (네트워크 안 거침)
- ChangeCipherSpec + Finished → 이제부터 암호화 통신 시작
TLS 1.3은 1-RTT로 더 빠르고 ECDHE만 써서 Forward Secrecy 보장됨.
5. Duplicate ACK랑 Fast Retransmit
Dup ACK가 뭔지
패킷이 순서대로 안 오면 수신측이 "이 번호 아직 없어" 하면서 같은 Ack를 계속 보냄. 이게 Duplicate ACK.
Fast Retransmit
Dup ACK를 3번 받으면 타임아웃 기다리지 않고 바로 재전송함. (RFC 5681) 타임아웃 방식은 200ms~1s 기다려야 하는데 Fast Retransmit은 수 ms 만에 끝남.
오늘 실제로 본 케이스
#76 Ack=5906 ← 1번째
#77 Ack=5906 ← 2번째 (Dup ACK)
#78 Ack=5906 ← 3번째 (Dup ACK) → 서버 Fast Retransmit 발동
#79 Seq=5906, Len=481 재전송
#80 Ack=6387 ← 정상 복귀 (5906+481=6387)
소요 시간: 약 6ms
원인은 서버가 ACK를 연속으로 빠르게 날리면서 타이밍이 약간 엇갈린 것. 실제 패킷 유실은 아니었고 #79 한 방으로 해결됨.
Fast Retransmit인지 어떻게 아냐
Wireshark가 [TCP Fast Retransmission] 태그를 안 붙여줘서 100% 확신은 못 함. 캡처가 중간부터 시작돼서 이전 Seq 기록이 없기 때문. 근거는
- #78 → #79 사이가 5.8ms → 타임아웃이면 최소 200ms
- #79 Seq가 정확히 5906에서 시작 → Dup ACK가 요청한 번호랑 일치
- Dup ACK 3회 직후에 바로 옴
pcap 분석이 대부분 이런 식의 추론
6. TCP Keep-Alive
연결이 살아있는지 주기적으로 확인하는 용도. Seq를 1 줄인 1바이트짜리 probe 패킷 보내고 ACK 기다림. Wireshark에서 [TCP Keep-Alive], [TCP Keep-Alive ACK]로 표시됨.
7. Seq > Ack 여도 정상인 경우 있음
Seq랑 Ack는 서로 다른 방향의 독립 카운터라서 직접 비교하면 안 됨.
Seq = 내가 보낸 데이터 카운터
Ack = 상대방이 보낸 데이터 카운터
클라이언트가 서버보다 훨씬 많이 보내는 상황(git push 같은 거)이면 당연히 클라이언트 Seq > 서버 Seq
오늘 #80에서 Seq=10869, Ack=6387 인 게 이상해 보였는데 그냥 클라이언트가 깃허브에 데이터를 훨씬 많이 보낸 거였음.