tcpdump: Phân Tích Gói Tin Mạng Từ Command Line Linux

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Bắt Đầu Nhanh: Bắt Gói Tin Đầu Tiên Trong 5 Phút

Nếu bạn đã từng phải debug một microservice bị lỗi lúc 2 giờ sáng mà không có Wireshark, bạn sẽ hiểu ngay tại sao tcpdump lại quan trọng đến vậy. Đây là công cụ đầu tiên tôi nghĩ đến khi có gì đó kỳ lạ xảy ra trên mạng — và chỉ cần nắm vài lệnh cơ bản, bạn sẽ không còn phải nghĩ đến cú pháp nữa mà dùng nó một cách tự nhiên.

Trước tiên, kiểm tra xem tcpdump đã được cài chưa:

tcpdump --version

Nếu chưa, cài đặt như sau:

# Debian/Ubuntu
sudo apt install tcpdump

# RHEL/CentOS/Rocky
sudo dnf install tcpdump

Giờ hãy bắt traffic trực tiếp trên interface chính:

sudo tcpdump -i eth0

Các gói tin sẽ hiện ra ngay lập tức. Nhấn Ctrl+C để dừng. Vậy là xong — bạn đã bắt đầu sniff traffic rồi. Output thô không thực sự hữu ích khi đứng một mình, vậy nên hãy làm cho nó có ích hơn.

Lệnh tôi dùng hàng ngày là giới hạn số gói và lưu vào file:

sudo tcpdump -i eth0 -c 100 -w capture.pcap

Lệnh này bắt đúng 100 gói tin và lưu vào file .pcap để phân tích sau — thậm chí có thể mở bằng Wireshark nếu cần phân tích giao thức chi tiết hơn.

Tìm Hiểu Sâu: Filters và Output

Chọn Interface Phù Hợp

Liệt kê tất cả các interface trước khi bắt đầu capture:

sudo tcpdump -D
# hoặc
ip link show

Trên server chạy Docker, bạn sẽ thấy docker0, eth0, lo, và một số cặp veth. Chọn nhầm interface là bỏ lỡ toàn bộ traffic cần theo dõi.

BPF Filters: Sức Mạnh Thực Sự

tcpdump sử dụng cú pháp Berkeley Packet Filter (BPF). Nắm vững nó và bạn có thể lọc chính xác traffic cần quan tâm. Đây là những filter tôi thực sự dùng trên môi trường production:

Lọc theo host:

sudo tcpdump -i eth0 host 192.168.1.50

Lọc theo port:

sudo tcpdump -i eth0 port 443
sudo tcpdump -i eth0 port 80 or port 443

Lọc theo giao thức:

sudo tcpdump -i eth0 tcp
sudo tcpdump -i eth0 udp
sudo tcpdump -i eth0 icmp

Kết hợp nhiều filter (src/dst + port):

# Traffic TỪ một host cụ thể trên port 3306 (MySQL)
sudo tcpdump -i eth0 src host 10.0.0.5 and port 3306

# Traffic ĐẾN app server trên port 8080
sudo tcpdump -i eth0 dst host 10.0.0.10 and port 8080

Loại bỏ nhiễu — bỏ SSH để không làm ngập terminal của bạn:

sudo tcpdump -i eth0 not port 22

Đọc Output

Một dòng tcpdump điển hình trông như thế này:

14:32:01.123456 IP 10.0.0.5.54321 > 10.0.0.10.80: Flags [S], seq 1234567890, win 65535, length 0
  • 14:32:01.123456 — timestamp với độ chính xác microsecond
  • IP 10.0.0.5.54321 > 10.0.0.10.80 — IP:port nguồn → IP:port đích
  • Flags [S]TCP flags: S=SYN, A=ACK, F=FIN, R=RST, P=PSH
  • length 0 — kích thước payload (0 với gói tin điều khiển thuần túy như SYN)

Thêm -n để bỏ qua DNS resolution (output nhanh hơn, ít rối hơn) và -nn để bỏ luôn cả việc resolve tên port:

sudo tcpdump -i eth0 -nn port 443

Nâng Cao: Các Tình Huống Production Thực Tế

Debug API Chậm

Khi một API endpoint có vẻ chậm nhưng bạn không biết là do mạng hay do ứng dụng, hãy bắt TCP handshake để đo độ trễ kết nối trực tiếp:

# Chỉ bắt gói SYN và SYN-ACK để đo thời gian thiết lập kết nối
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' and port 8080

Khoảng cách lớn giữa SYN và SYN-ACK nghĩa là server đang gặp khó khăn trong việc chấp nhận kết nối. SYN-ACK trả về nhanh nhưng response kéo dài? Nút thắt cổ chai nằm ở ứng dụng của bạn, không phải mạng.

Theo Dõi DNS Resolution Theo Thời Gian Thực

sudo tcpdump -i eth0 -nn udp port 53

Lệnh này đã cứu tôi nhiều lần. Tôi từng phát hiện một container bị cấu hình sai đang bắn khoảng 8.000 DNS request mỗi giây vào internal resolver — gần như làm nó sụp đổ. Nếu không có packet inspection trực tiếp, dạng vấn đề này sẽ ẩn mình sau các metric latency mơ hồ và timeout.

Bắt HTTP Headers (Traffic Không Mã Hóa)

# -A in payload gói tin dưới dạng ASCII
sudo tcpdump -i eth0 -A -nn port 80 | grep -E 'GET|POST|Host:|Content-Type:'

Cách này chỉ hoạt động với HTTP thuần — với HTTPS bạn cần mitmproxy hoặc SSL key logging. Tuy nhiên, với các internal service, legacy API, hoặc traffic container-to-container trên private network, nó cực kỳ tiện dụng.

Lưu và Đọc Lại Capture

# Lưu capture
sudo tcpdump -i eth0 -w /tmp/debug-$(date +%Y%m%d-%H%M%S).pcap not port 22

# Đọc lại sau (không cần quyền root để đọc)
tcpdump -r /tmp/debug-20260401-143200.pcap

# Đọc với filter áp dụng cho file đã lưu
tcpdump -r /tmp/debug-20260401-143200.pcap port 5432

Thói quen đặt timestamp vào tên file là điều tôi học được sau khi lạc mất năm file capture khác nhau trong một sự cố lúc nửa đêm. Chuyện nhỏ, nhưng tiết kiệm khá nhiều nhầm lẫn khi bạn đang căng thẳng.

Xoay Vòng Capture Cho Phân Tích Dài Hạn

# Chia thành các file 100MB, xoay mỗi 60 giây, giữ 10 file
sudo tcpdump -i eth0 -w /tmp/capture-%Y%m%d-%H%M%S.pcap \
  -C 100 -G 60 -W 10 not port 22

Đây là cách tôi hay dùng để chạy tcpdump qua đêm cho một sự cố không liên tục. Bạn có một cửa sổ traffic rolling 10 phút mà không lo đầy đĩa.

Mẹo Thực Tế Từ Kinh Nghiệm

Mẹo 1: Luôn Loại Trừ SSH Khi Capture Tương Tác

Quên điều này và terminal của bạn sẽ ngập tràn traffic SSH của chính mình — nhiễu vô nghĩa che khuất những gói tin bạn thực sự cần:

sudo tcpdump -i eth0 not port 22 and not port 2222

Mẹo 2: Dùng -v, -vv, -vvv Để Xem Chi Tiết Hơn

# -v: TTL, tổng độ dài, IP options
# -vv: chi tiết hơn về NFS/SMB/DNS
# -vvv: giải mã đầy đủ khi có thể
sudo tcpdump -i eth0 -vv icmp

Mẹo 3: Capture Trên Docker Bridge Cho Container Traffic

# Tìm interface Docker bridge của bạn
ip link show | grep docker

# Bắt traffic giữa các container
sudo tcpdump -i docker0 -nn not port 22

Cách này cho phép bạn kiểm tra traffic giữa các container mà không cần động đến interface ngoài của host — chính xác là thứ bạn cần khi debug một Docker Compose stack đang hoạt động sai.

Mẹo 4: tcpdump + grep Để Tìm Kiếm Pattern Nhanh

# Theo dõi connection reset theo thời gian thực
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-rst != 0' 2>/dev/null

# Đếm gói tin theo source IP (pipe sang sort)
sudo tcpdump -i eth0 -nn -c 1000 2>/dev/null | \
  awk '{print $3}' | cut -d'.' -f1-4 | sort | uniq -c | sort -rn | head -20

Mẹo 5: Kết Hợp với tshark Để Phân Tích Có Script

tshark là phiên bản CLI của Wireshark — đọc file .pcap với khả năng phân tích giao thức phong phú hơn nhiều. Capture bằng tcpdump, phân tích bằng tshark:

# Capture
sudo tcpdump -i eth0 -w capture.pcap port 5432

# Phân tích traffic PostgreSQL với tshark
tshark -r capture.pcap -Y 'pgsql' -T fields -e frame.time -e ip.src -e ip.dst

Tôi đã dùng combo này để theo dõi các query PostgreSQL chậm qua một network hop. File pcap làm rõ ngay lập tức những query nào đang làm quá tải connection pool — điều mà application log không hề cho bất kỳ gợi ý nào.

Bảng Tham Khảo Nhanh

  • tcpdump -i eth0 — bắt trên interface
  • tcpdump -i any — bắt trên TẤT CẢ interface
  • tcpdump -nn — không resolve DNS/tên port
  • tcpdump -c 100 — dừng sau 100 gói tin
  • tcpdump -w file.pcap — ghi vào file
  • tcpdump -r file.pcap — đọc từ file
  • tcpdump -A — hiển thị payload dạng ASCII
  • tcpdump -X — hiển thị payload dạng hex + ASCII
  • tcpdump -e — hiển thị Ethernet/MAC header
  • tcpdump host X.X.X.X — lọc theo host
  • tcpdump port 443 — lọc theo port
  • tcpdump net 10.0.0.0/24 — lọc theo subnet

tcpdump càng dùng càng thành thạo. Hãy bắt đầu trên môi trường dev hoặc staging — không áp lực, không rủi ro. Làm quen với cách đọc output. Khi sự cố thực sự xảy ra lúc 3 giờ sáng, bạn sẽ tự nhiên nghĩ đến nó và có câu trả lời trong vài phút, thay vì mất hàng giờ.

Share: