Hướng dẫn sử dụng Conntrack trên Linux: Giám sát, gỡ lỗi và tối ưu bảng theo dõi kết nối mạng

Network tutorial - IT technology blog
Network tutorial - IT technology blog

Quick start: Xem và quản lý bảng conntrack trong 5 phút

Khi Linux làm NAT gateway, load balancer hay chạy firewall iptables/nftables, kernel sẽ âm thầm ghi nhớ từng phiên mạng. Bộ công cụ conntrack-tools cho phép bạn can thiệp trực tiếp vào dữ liệu này thay vì phải đọc file raw phức tạp trong /proc.

Cài đặt gói lệnh trên Debian/Ubuntu:

sudo apt update && sudo apt install -y conntrack

Với RHEL, Rocky Linux hoặc CentOS Stream:

sudo dnf install -y conntrack-tools

Kiểm tra nhanh tổng số kết nối kernel đang theo dõi:

sudo conntrack -C

Lấy 10 kết nối TCP đang ở trạng thái ESTABLISHED:

sudo conntrack -L -p tcp --status ESTABLISHED | head -n 10

Lọc các phiên gửi tới máy chủ database nội bộ (ví dụ IP 10.0.0.50):

sudo conntrack -L -d 10.0.0.50

Cần trảm gấp toàn bộ kết nối từ một IP đang flood traffic? Dùng ngay cờ -D:

sudo conntrack -D -s 203.0.113.88

Bản chất: Conntrack là gì và hoạt động ra sao?

Hãy hình dung server giống như sảnh tòa nhà văn phòng đón hàng nghìn lượt khách mỗi ngày. Khách lạ bước vào, bảo vệ kiểm tra căn cước, ghi sổ nhật ký rồi mới bấm thang máy. Nếu người đó quay lại sau vài phút, bảo vệ chỉ liếc qua cuốn sổ: "Đã đăng ký rồi, cho qua". Không ai phải xét duyệt lại từ đầu.

Conntrack (Connection Tracking) chính là cuốn sổ trực đó của Linux kernel. Đây là subsystem cốt lõi thuộc framework Netfilter. Nhờ nó, firewall mới hiểu được gói tin thuộc phiên nào để chạy rule kinh điển này:

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Với mỗi gói tin đi qua, kernel bóc tách bộ 5-tuple: Source IP, Destination IP, Source Port, Destination Port và Protocol. Dữ liệu này được băm (hash) rồi lưu thẳng vào bảng hash table trong RAM.

4 trạng thái kết nối cần nhớ

  • NEW: Gói tin đầu tiên mở luồng dữ liệu, điển hình là cờ TCP SYN.
  • ESTABLISHED: Phiên đã thông hai chiều sau khi hoàn tất bắt tay 3 bước (3-way handshake).
  • RELATED: Kết nối phụ sinh ra từ một phiên có sẵn, ví dụ kênh truyền dữ liệu FTP passive hoặc gói báo lỗi ICMP unreachable.
  • UNTRACKED: Gói tin bị bỏ qua không theo dõi, thường gán qua bảng raw để tiết kiệm tài nguyên.

Cách đọc một dòng log conntrack

Chạy lệnh conntrack -L, bạn sẽ nhận được output dạng:

tcp      6 431999 ESTABLISHED src=192.168.1.15 dst=1.1.1.1 sport=54212 dport=443 src=1.1.1.1 dst=192.168.1.15 sport=443 dport=54212 [ASSURED] mark=0 use=1

Ý nghĩa từng thông số:

  • tcp 6: Tên giao thức TCP kèm số hiệu protocol chuẩn (TCP là 6, UDP là 17).
  • 431999: Thời gian TTL đếm lùi (tính bằng giây). Hết số giây này mà không có packet mới, bản ghi sẽ bị dọn dẹp.
  • ESTABLISHED: Trạng thái hiện tại của phiên TCP.
  • Hai cụm src/dst/sport/dport: Cụm đầu là chiều gửi đi (original), cụm sau là luồng phản hồi mong đợi (reply).
  • [ASSURED]: Kernel đã thấy traffic trả về cả hai chiều, không còn là kết nối một phía.

Xử lý sự cố thực tế: Khi bảng conntrack bị tràn

Triệu chứng rất quái gở: CPU chỉ ăn 30%, RAM trống thênh thang, băng thông chưa đầy nửa port 1Gbps, nhưng API liên tục timeout vào giờ cao điểm. Ping thử gateway thì rớt gói 15-20% theo từng đợt.

Kiểm tra switch và dây mạng đều bình thường. Chỉ khi gõ dmesg -T, thủ phạm mới lộ diện:

nf_conntrack: table full, dropping packet

Server lúc đó gánh NAT cho cụm Kubernetes với hơn 80 microservices. Mỗi giây có hàng chục nghìn request HTTP ngắn hạn mở ra rồi đóng lại. Bảng conntrack chạm trần 65.536 entries mặc định. Để bảo vệ RAM không bị cạn kiệt, kernel tự động vứt bỏ mọi gói tin mới.

Kiểm tra ngưỡng chịu tải hiện tại

Xem số entry tối đa kernel đang cho phép:

sysctl net.netfilter.nf_conntrack_max

Xem số bucket trong bảng băm:

cat /sys/module/nf_conntrack/parameters/hashsize

Công thức mở rộng an toàn và tính toán RAM

Tỷ lệ tối ưu giữa nf_conntrack_max và hashsize là 4:1 hoặc 8:1. Mỗi entry trên hệ thống 64-bit tốn khoảng 320 bytes bộ nhớ.

Nâng bảng lên 1.048.576 entries (1M kết nối)? Bạn chỉ mất khoảng 335 MB RAM. Một cái giá quá rẻ trên những server 32GB hay 64GB RAM hiện nay.

Áp dụng ngay trên hệ thống đang chạy (runtime):

sudo sysctl -w net.netfilter.nf_conntrack_max=1048576
echo 262144 | sudo tee /sys/module/nf_conntrack/parameters/hashsize

Để giữ nguyên thông số sau khi reboot, thêm vào file /etc/sysctl.d/99-conntrack.conf:

net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 21600
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30

Đồng thời ghim giá trị hashsize vào /etc/modprobe.d/conntrack.conf:

options nf_conntrack hashsize=262144

Nạp lại toàn bộ file sysctl vừa tạo:

sudo sysctl --system

Kinh nghiệm thực chiến cho server chịu tải cao

  • Hạ ngay timeout của TCP ESTABLISHED: Mặc định Linux giữ phiên này tới 432.000 giây (tận 5 ngày). Nếu client ngắt mạng đột ngột mà không gửi FIN/RST, entry đó sẽ nằm chình ình trong bảng gần một tuần. Hãy kéo xuống 6 giờ (21.600 giây) hoặc 2 giờ với server web công cộng.
  • Bật NOTRACK cho traffic tải lớn: Nếu server chạy HAProxy, Nginx reverse proxy hoặc DNS công cộng, bạn không nhất thiết phải theo dõi state từng gói tin. Bỏ qua conntrack ở bảng raw sẽ giải phóng lượng lớn tài nguyên CPU và RAM:
sudo iptables -t raw -A PREROUTING -p tcp -m multiport --dports 80,443 -j NOTRACK
sudo iptables -t raw -A PREROUTING -p udp --dport 53 -j NOTRACK
  • Bắt sự kiện trực tiếp khi gỡ lỗi: Lệnh sau giúp bạn quan sát trực tiếp từng phiên kết nối vừa sinh ra hoặc vừa bị hủy theo thời gian thực:
sudo conntrack -E -e NEW,DESTROY
  • Cấu hình alert trước khi sự cố xảy ra: Giám sát tỷ lệ node_nf_conntrack_entries / node_nf_conntrack_entries_limit trên Grafana. Đặt ngưỡng cảnh báo khi con số chạm mốc 75-80%. Điều này giúp team hạ tầng xử lý kịp thời trước khi bảng đầy và gói tin bắt đầu bị drop giữa đêm.
Share: