Khởi động nhanh (5 phút)
Cách đây sáu tháng, các node cổng thanh toán của chúng tôi bắt đầu xuất hiện lỗi 504 gateway timeout rải rác ở mức khoảng 3.500 request/giây. Với các instance Ubuntu headless tối giản nằm trong AWS VPC riêng tư, việc chạy một công cụ GUI như Wireshark là điều bất khả thi. Chúng tôi buộc phải kiểm tra trực tiếp traffic mạng thô ngay trên máy chủ. Sự cố đó đã biến tcpdump thành tiện ích ứng cứu sự cố mặc định của chúng tôi, và đến nay nó vẫn là cách nhanh nhất để truy vết tình trạng drop gói tin ở tầng socket.
Bạn chỉ mất vài phút để bắt đầu. Hầu hết các bản phân phối enterprise đều cài sẵn tcpdump. Nếu bắt đầu từ một container image tối giản như Debian, Alpine hoặc RHEL, hãy cài đặt nó trước:
# Trên Debian/Ubuntu
sudo apt-get update && sudo apt-get install -y tcpdump
# Trên RHEL/AlmaLinux/Rocky
sudo dnf install -y tcpdump
Kiểm tra các network interface khả dụng để bắt gói tin:
sudo tcpdump -D
Lệnh này sẽ liệt kê các interface vật lý và ảo đang hoạt động như eth0, ens3, cùng interface tổng hợp any. Để bắt đầu theo dõi traffic trực tiếp trên một interface cụ thể mà không cần chờ phân giải DNS, hãy chạy:
sudo tcpdump -i eth0 -n
Cờ -n vô hiệu hóa việc phân giải reverse DNS. Bỏ qua các query PTR giúp ngăn tcpdump làm nghẽn các upstream DNS resolver trong khi bạn đang kiểm tra luồng dữ liệu. Nhấn Ctrl+C khi đã thu thập đủ dữ liệu mẫu. Lệnh sẽ kết thúc với bảng tóm tắt chi tiết thống kê số frame đã bắt, số lượng khớp bộ lọc và số gói tin bị drop ở kernel buffer.
Phân tích chuyên sâu
Việc dump gói tin mà không lọc sẽ làm tràn bộ nhớ đệm terminal ngay lập tức. Trên đường truyền 10 Gbps, các bản bắt gói tin thô có thể trôi qua hơn 50.000 gói tin trước khi bạn kịp nhấn Ctrl+C. Để kiểm soát được luồng dữ liệu khổng lồ này, bạn cần học cách đọc định dạng gói tin và lọc chính xác bằng Berkeley Packet Filters (BPF).
Phân tích định dạng đầu ra của tcpdump
Một dòng TCP packet header điển hình được ghi lại bằng tcpdump -nn -S có dạng như sau:
14:22:01.408219 IP 192.168.1.50.44322 > 10.0.0.15.80: Flags [P.], seq 1827401:1827945, ack 392019, win 502, length 544
Các thành phần quan trọng bao gồm:
- Timestamp: Thời gian hệ thống với độ chính xác cao đến micro giây (
14:22:01.408219). - Source > Destination: Client
192.168.1.50:44322gửi dữ liệu đến web server10.0.0.15:80. - TCP Flags:
[P.]biểu thị cờ Push (P) và Acknowledge (.). Các cờ phổ biến gồm[S](SYN),[S.](SYN-ACK),[F](FIN),[R](RST), và[.](pure ACK). - Sequence và ACK number: Byte offset dùng để theo dõi quá trình truyền tải payload. Ở đây,
seq 1827401:1827945xác nhận 544 byte dữ liệu đã được gửi đi (1.827.945 – 1.827.401 = 544). - Window size & Length: Kích thước bộ đệm nhận được thông báo (
win 502) và kích thước payload của segment (length 544).
Lọc mục tiêu với Berkeley Packet Filters (BPF)
Biểu thức BPF chạy trực tiếp trong kernel space trước khi các gói tin chạm tới bộ đệm bộ nhớ ở user-space. Loại bỏ sớm các frame không liên quan giúp tránh quá tải CPU và ngăn chặn tình trạng tràn ring buffer. Bạn có thể thu hẹp phạm vi bắt gói tin theo địa chỉ IP, dải CIDR, cổng hoặc giao thức tầng transport:
# Bắt traffic HTTP và HTTPS liên quan đến một IP client cụ thể
sudo tcpdump -i eth0 -nn "host 192.168.1.100 and (port 80 or port 443)"
# Giám sát traffic gửi đến subnet cơ sở dữ liệu bên ngoài
sudo tcpdump -i eth0 -nn "dst net 10.10.0.0/16 and port 5432"
Kết hợp các toán tử điều kiện như and, or, và not cho phép bạn loại bỏ các gói tin SSH gây nhiễu từ chính phiên terminal hiện tại:
sudo tcpdump -i any -nn "not port 22"
Kỹ thuật nâng cao
Khi truy vết các trường hợp phức tạp (edge cases)—như định tuyến bất đối xứng (asymmetric routing) hay kết nối upstream bị reset chập chờn—các bộ lọc theo cổng cơ bản sẽ không đủ đáp ứng. Hai kỹ thuật sau sẽ giúp bạn giải quyết các bài toán khó: xuất luồng bắt gói tin ra file nhị phân .pcap và lọc theo byte offset thô trong TCP header.
Ghi và đọc file PCAP để phân tích offline
Đọc dữ liệu terminal trực tiếp khi lưu lượng tăng đột biến rất dễ làm bạn bỏ sót dấu vết quan trọng. Thay vào đó, hãy ghi trực tiếp luồng nhị phân thô ra đĩa, sau đó phân tích tại local hoặc mở bằng Wireshark:
# Lưu toàn bộ payload vào file capture.pcap với giới hạn 50.000 gói tin
sudo tcpdump -i eth0 -nn -s 0 -c 50000 -w /tmp/api_traffic.pcap "port 8080"
Để phân tích file đã lưu mà không cần phát lại các gói tin trực tiếp:
tcpdump -nn -r /tmp/api_traffic.pcap "tcp[tcpflags] & tcp-rst != 0"
Cô lập các TCP Handshake và Reset kết nối
Việc chẩn đoán timeout tại các proxy trung gian hoặc phiên kết nối bị drop đòi hỏi phải truy vết các gói tin RST bất thường và các gói SYN không được phản hồi (unacknowledged). BPF cho phép bạn kiểm tra bitwise trên byte thứ 13 của TCP header, nơi chứa các cờ điều khiển:
# Chỉ bắt các yêu cầu khởi tạo kết nối (SYN không có ACK)
sudo tcpdump -i eth0 -nn "tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0"
# Phát hiện ngắt kết nối đột ngột (các gói tin TCP RST)
sudo tcpdump -i eth0 -nn "tcp[tcpflags] & (tcp-rst) != 0"
Nếu cần kiểm tra header HTTP chưa mã hóa hoặc các truy vấn Redis thô, hãy dùng cờ hiển thị dạng ASCII (-A) hoặc kết hợp hex/ASCII (-X), đồng thời lọc các gói tin thực sự chứa dữ liệu payload:
# Lọc bỏ các gói pure ACK và hiển thị các byte payload dưới dạng ASCII
sudo tcpdump -i eth0 -nn -A -s 0 "port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12:1] & 0xf0)>>2)) != 0)"
Kinh nghiệm thực tế
Bắt gói tin trên các hệ thống có throughput cao có thể gây quá tải CPU và I/O đĩa nếu không giới hạn thông số. Những nguyên tắc vận hành sau sẽ giúp việc giám sát luôn an toàn trên các máy chủ production bận rộn:
- Giới hạn snaplen (
-s): Các phiên bảntcpdumphiện đại mặc định bắt toàn bộ gói tin (262.144 byte). Nếu bạn chỉ cần metadata định tuyến và các cờ, hãy giới hạn kích thước gói bắt bằng-s 96. Trên các node API 4 core, 16 GB của chúng tôi đang xử lý 12.000 gói tin/giây, việc giảm snaplen xuống 96 byte đã giúp giảm băng thông ghi đĩa từ 18 MB/s xuống dưới 1,2 MB/s. - Luôn kết hợp
-nvới-nn: Trong khi-ndừng phân giải reverse DNS cho IP,-nnsẽ ngăn việc chuyển đổi port sang tên dịch vụ (service name). Nếu không có nó,tcpdumpsẽ tra cứu file/etc/servicesđể chuyển port443thànhhttpshoặc port3306thànhmysql. Dùng cả hai cờ này giúp giảm độ trễ CPU không đáng có trong các đợt lưu lượng tăng đột biến. - Luân chuyển file để tránh tràn ổ cứng: Các phiên debug kéo dài có thể âm thầm làm đầy phân vùng root. Hãy kết hợp
-C(giới hạn dung lượng file theo triệu byte) với-W(số lượng file tối đa) để tạo một circular buffer giới hạn:
# Ring buffer xoay vòng: lưu tối đa 5 file, mỗi file 100MB
sudo tcpdump -i eth0 -nn -s 96 -C 100 -W 5 -w /var/log/traffic_roll.pcap "port 443"
- Kiểm tra số lượng gói tin bị drop bởi kernel: Khi kết thúc phiên bắt gói tin bằng
Ctrl+C, hãy để ý dòng tóm tắt packets dropped by kernel. Nếu con số này khác 0, nghĩa là socket buffer đã bị đầy trước khitcpdumpkịp đọc dữ liệu. Khi gặp tình trạng drop gói, hãy giới hạn snaplen bằng-s 96, tối ưu lại biểu thức BPF hoặc ghi tạm file bắt gói tin vào một ramdisk như/dev/shm.
Một khi đã nắm vững các biểu thức BPF và byte offset của các cờ, tcpdump sẽ biến các sự cố mạng mơ hồ thành dữ liệu rõ ràng, có thể xử lý được. Nó loại bỏ việc phỏng đoán vu vơ về đường truyền gói tin và giúp bạn xác định chính xác các kết nối bắt tay thất bại hay phiên làm việc bị drop chỉ trong vài phút.

