Bối cảnh & Tại sao cần conntrackd kết hợp Keepalived
Dựng gateway dự phòng bằng Keepalived trên Linux là bài toán quen thuộc của dân quản trị mạng. Khi router chính (Master) gặp sự cố, Keepalived chuyển Virtual IP (VIP) sang máy dự phòng (Backup) chỉ mất chưa đầy một giây. Mạng thông lại rất nhanh. Thế nhưng, hệ quả sau đó mới đau đầu: cuộc gọi VoIP ngắt giữa chừng, tiến trình tải file 20 GB qua HTTPS đứt đoạn, và toàn bộ phiên SSH của anh em sysadmin văng sạch.
Thủ phạm nằm ở cơ chế Stateful Firewall của Linux Netfilter (iptables/nftables). Linux dùng bảng theo dõi kết nối (conntrack) để ghi nhớ trạng thái từng phiên TCP/UDP. Khi VIP nhảy sang node Backup, node này hoàn toàn không có thông tin về các session đang mở trước đó. Thấy gói tin gửi đến mang cờ ACK mà thiếu bước bắt tay 3 bước (SYN, SYN-ACK) ban đầu, kernel coi đó là gói tin bất thường (INVALID) và drop thẳng tay.
Nếu bạn vận hành gateway cho văn phòng khoảng 50–100 người hay một cụm cụm server nội bộ, sự cố rớt session kiểu này sẽ làm gián đoạn công việc của cả công ty. Giải pháp xử lý triệt để là triển khai conntrackd (connection tracking daemon).
Daemon này chạy ngầm ở tầng userspace. Nó liên tục copy bảng theo dõi kết nối giữa hai node thông qua card mạng đồng bộ. Khi Keepalived kích hoạt node Backup lên Master, conntrackd lập tức nạp toàn bộ session trong cache vào kernel. Kết quả? Chuyển dịch gateway trong suốt. Người dùng gần như không nhận ra sự cố vừa xảy ra.
Cài đặt các gói cần thiết
Mô hình triển khai gồm 2 node Linux (Ubuntu 22.04 / Debian 12):
- Node 1 (FW-01): LAN IP
192.168.1.2/24(eth0), Sync IP10.0.0.1/30(eth1) - Node 2 (FW-02): LAN IP
192.168.1.3/24(eth0), Sync IP10.0.0.2/30(eth1) - VIP Gateway:
192.168.1.1gán trên card eth0
Lưu ý phần cứng: Luôn dành riêng một card mạng vật lý (ở đây là eth1 nối trực tiếp bằng cáp chéo hoặc DAC) để chạy traffic đồng bộ session. Tuyệt đối không dùng chung dải LAN. Khi hệ thống có khoảng 20.000 kết nối đồng thời, lượng event conntrack sinh ra có thể đạt hàng nghìn gói mỗi giây (PPS), rất dễ gây nghẽn broadcast domain nội bộ.
Cài đặt Keepalived, conntrack và conntrackd trên cả hai máy:
sudo apt update
sudo apt install -y keepalived conntrack conntrackd
Bật chuyển tiếp gói tin (IP Forwarding) và nới lỏng kiểm tra TCP sequence (thực hiện trên cả 2 node):
cat <<EOF | sudo tee /etc/sysctl.d/99-firewall-sync.conf
net.ipv4.ip_forward = 1
net.netfilter.nf_conntrack_tcp_be_liberal = 1
EOF
sudo sysctl -p /etc/sysctl.d/99-firewall-sync.conf
Tham số nf_conntrack_tcp_be_liberal = 1 giữ vai trò sống còn. Khi vừa failover, gói tin sync có thể đến chậm hơn vài mili-giây so với traffic thực tế. Thiết lập này bảo kernel chấp nhận các gói tin nằm ngoài TCP window dự kiến thay vì gạt bỏ nhầm.
Cấu hình chi tiết Keepalived và conntrackd
1. Cấu hình conntrackd
File cấu hình chính đặt tại /etc/conntrackd/conntrackd.conf. Chúng ta chạy chế độ FTFW (Fault-Tolerant Framework) qua giao thức UDP Unicast.
Nội dung file trên Node 1 (FW-01):
sudo tee /etc/conntrackd/conntrackd.conf <<'EOF'
Sync {
Mode FTFW {
ResendQueueSize 10240
CommitTimeout 180
PurgeTimeout 60
}
UDP {
IPv4_address 10.0.0.1
IPv4_Destination_Address 10.0.0.2
Port 3780
Interface eth1
SndSocketBuffer 12492800
RcvSocketBuffer 12492800
Checksum on
}
}
General {
Systemd on
Nice -20
Scheduler {
Type FIFO
Priority 99
}
HashSize 32768
HashLimit 131072
LogFile on
Syslog off
LockFile /var/lock/conntrackd.lock
UNIX {
Path /var/run/conntrackd.ctl
Backlog 20
}
NetlinkBufferSize 2097152
NetlinkBufferSizeMaxGrowth 2
Filter From Userspace {
Protocol Accept {
TCP
UDP
ICMP
}
Address Ignore {
IPv4_address 127.0.0.1
IPv4_address 10.0.0.0/30
}
}
}
EOF
Thông số SndSocketBuffer và RcvSocketBuffer được nâng lên mức 12 MB. Mức đệm này giúp daemon không bị drop gói tin Netlink khi mạng chịu tải đột biến. Mục Address Ignore loại trừ dải 10.0.0.0/30 để tránh việc daemon tự đồng bộ chính các gói tin UDP sync.
Trên Node 2 (FW-02), copy cấu hình tương tự nhưng đảo ngược hai địa chỉ IP trong block UDP:
IPv4_address 10.0.0.2
IPv4_Destination_Address 10.0.0.1
2. Script kích hoạt trạng thái cho conntrackd
Khi Keepalived hoán đổi vai trò, nó phải ra lệnh cho conntrackd: nạp session vào kernel khi lên Master, hoặc giải phóng cache khi về Backup. Tạo file script tại /etc/conntrackd/primary-backup.sh trên cả 2 node:
sudo tee /etc/conntrackd/primary-backup.sh <<'EOF'
#!/bin/bash
case "$1" in
primary)
# Commit du lieu tu external cache vao kernel conntrack table
conntrackd -c
# Gui tin hieu resync lai session hien tai
conntrackd -f
;;
backup)
# Giai phong cache ngoai khi ve trang thai du phong
conntrackd -t
;;
fault)
conntrackd -t
;;
esac
exit 0
EOF
sudo chmod +x /etc/conntrackd/primary-backup.sh
3. Cấu hình Keepalived
Một điểm mấu chốt: để tùy chọn nopreempt hoạt động đúng, cả hai node đều phải khai báo state BACKUP ban đầu. Node chính phân định bằng mức priority cao hơn. Nếu bạn để state MASTER kèm nopreempt, node chính sẽ phớt lờ cờ này mỗi khi reboot và lập tức giật lại VIP, gây chớp mạng 2 lần.
Cấu hình /etc/keepalived/keepalived.conf trên Node 1 (FW-01):
vrrp_sync_group VG1 {
group {
VI_LAN
}
notify_master "/etc/conntrackd/primary-backup.sh primary"
notify_backup "/etc/conntrackd/primary-backup.sh backup"
notify_fault "/etc/conntrackd/primary-backup.sh fault"
}
vrrp_instance VI_LAN {
state BACKUP
interface eth0
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass Secr3tPwD
}
virtual_ipaddress {
192.168.1.1/24 dev eth0
}
nopreempt
}
Cấu hình trên Node 2 (FW-02) hoàn toàn tương tự, chỉ giảm priority xuống 100:
vrrp_sync_group VG1 {
group {
VI_LAN
}
notify_master "/etc/conntrackd/primary-backup.sh primary"
notify_backup "/etc/conntrackd/primary-backup.sh backup"
notify_fault "/etc/conntrackd/primary-backup.sh fault"
}
vrrp_instance VI_LAN {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass Secr3tPwD
}
virtual_ipaddress {
192.168.1.1/24 dev eth0
}
nopreempt
}
Bật và kích hoạt dịch vụ trên cả hai máy:
sudo systemctl restart conntrackd
sudo systemctl enable conntrackd
sudo systemctl restart keepalived
sudo systemctl enable keepalived
Kiểm tra & Giám sát hoạt động
Kiểm tra xem dữ liệu session có thực sự đi qua sợi cáp sync hay không bằng các bước sau.
1. Xem thống kê đồng bộ (Stats)
Chạy lệnh kiểm tra trên Node 2 (FW-02):
sudo conntrackd -s
Quan sát bảng xuất ra. Mục cache (external) hiển thị số lượng session nhận từ Node 1. Nếu chỉ số current active connections tăng theo lượng truy cập của client, đường sync đang hoạt động chuẩn:
cache (external):
current active connections: 142
connections created: 520 failed: 0
connections updated: 310 failed: 0
connections destroyed: 378 failed: 0
2. Thử nghiệm ngắt kết nối thực tế
Để kiểm chứng độ ổn định:
- Tại máy trạm client (IP
192.168.1.50), đặt default gateway về VIP192.168.1.1. - Mở phiên SSH ra ngoài Internet hoặc chạy lệnh tải file lớn:
curl -O https://speed.hetzner.de/100MB.bin. - Trên FW-01, giả lập sự cố đột ngột bằng cách dừng Keepalived:
sudo systemctl stop keepalived
Quan sát máy trạm: Quá trình tải file chỉ khựng lại chừng 0.5 giây rồi tiếp tục chạy đến 100%. Phiên SSH không hề báo lỗi Broken pipe.
Mở log trên FW-02 để xem xác nhận:
sudo tail -f /var/log/conntrackd.log
Hệ thống ghi nhận sự kiện nạp toàn bộ external cache vào kernel table. Đây là mô hình gateway Linux có chi phí đầu tư gần như bằng 0 nhưng mang lại độ tin cậy tương đương các thiết bị phần cứng chuyên dụng.

