Tường Lửa Liên Tục Phá Hỏng Quá Trình Deploy Của Tôi
Sáu tháng trước, tôi đang quản lý 12 VPS Linux trải dài trên ba nhà cung cấp cloud khác nhau. Mỗi server có một đống rule iptables riêng — một số sao chép từ Stack Overflow, một số thừa hưởng từ các sysadmin trước, và một số không ai còn nhớ đã viết ra. Mỗi lần deploy là một canh bạc. Một rule ip6tables bị bỏ sót sẽ âm thầm để traffic IPv6 đi qua mà không được lọc. Một sự không khớp arptables trên KVM host có thể làm hỏng định tuyến nội bộ trong nhiều giờ trước khi ai đó nhận ra.
Ba năm quản lý hệ thống VPS dạy tôi một điều: kiểm tra mọi thứ trước khi đụng vào production. Nhưng dù kiểm tra kỹ đến đâu cũng không giải quyết được vấn đề thiết kế căn bản của iptables. Bạn không quản lý một tường lửa — bạn đang phải xoay xở với bốn hệ thống con riêng biệt hoàn toàn không biết gì về nhau.
Tại Sao Iptables Đang Lỗi Thời
Hầu hết những cơn đau đầu về tường lửa của tôi đều bắt nguồn từ thiết kế của iptables — được xây dựng từ thời Linux 2.4 khi IPv6 còn là lý thuyết và lọc ARP chỉ là tính năng phụ.
Đây là những gì bạn thực sự cần quản lý với iptables trên một server hiện đại:
- iptables — lọc gói tin IPv4 và NAT
- ip6tables — các rule hoàn toàn giống, nhưng cho IPv6
- arptables — lọc ở cấp độ ARP
- ebtables — lọc Ethernet bridge
Một rule bạn viết cho IPv4 không có tác dụng gì với IPv6. Mỗi lần thay đổi chính sách đồng nghĩa với việc phải sửa ít nhất hai bộ rule riêng biệt. Việc áp dụng một bản vá bảo mật cho iptables mà quên mất ip6tables hoàn toàn là chuyện bình thường. Tôi đã thấy các server production được khóa chặt trên IPv4 trong khi địa chỉ IPv6 của chúng chấp nhận kết nối từ bất kỳ đâu.
Hiệu năng giảm theo cách có thể đoán trước trên các server bận rộn. Mỗi lần đánh giá gói tin phải duyệt qua một danh sách rule tuyến tính. Khi vượt 300 rule — không phải hiếm trong môi trường multi-tenant — chi phí xử lý thể hiện rõ trong các bài benchmark độ trễ. Việc tải lại rule cũng không thực sự atomic. iptables-restore gần đạt được điều đó, nhưng vẫn có một khoảng thời gian ngắn trong quá trình tải lại mà traffic có thể lọt qua hoặc bị drop bất ngờ.
Các Lựa Chọn Thay Thế: Bạn Thực Sự Đang Chọn Gì
Khi quyết định giải quyết vấn đề này, tôi thu hẹp lại còn ba hướng:
Phương án 1: Tiếp tục dùng Iptables với Công Cụ Tốt Hơn
Các công cụ như ferm hay script iptables-save/restore có thể giảm bớt sự trùng lặp. Bạn viết rule một lần và sinh ra cả output iptables lẫn ip6tables. Cách này hoạt động, nhưng bạn vẫn đang vá víu trên một nền tảng đã nứt. Vấn đề đánh giá tuyến tính vẫn còn đó, và arptables/ebtables vẫn tách biệt.
Phương án 2: UFW hoặc Firewalld
UFW (Ubuntu) và firewalld (RHEL/Fedora) là các lớp trừu tượng cấp cao tự động sinh ra rule iptables phía dưới. Ổn với các server đơn giản — mở port 22, cho phép HTTP, chặn tất cả còn lại. Nhưng ngay khi bạn cần rule NAT, chain tùy chỉnh, hay bất cứ thứ gì phức tạp hơn allow/deny cơ bản, bạn sẽ phải chiến đấu với chính lớp trừu tượng đó. Firewalld đã thêm backend nftables trong các phiên bản gần đây. Đó là dấu hiệu cho thấy nó đang đi về đâu.
Phương án 3: Nftables — Giải Pháp Thay Thế Hiện Đại
Nftables hợp nhất iptables, ip6tables, arptables và ebtables vào một framework duy nhất. Đánh giá rule sử dụng cấu trúc dữ liệu dựa trên set thay vì danh sách tuyến tính — nhanh hơn đáng kể khi vượt vài trăm rule. Thay thế rule atomic hoạt động theo cách tự nhiên, không phải xấp xỉ. Cú pháp đủ dễ đọc để một kỹ sư mới có thể hiểu một bộ rule mà không cần tra tài liệu.
Được tích hợp vào kernel từ phiên bản 3.13 (tháng 1 năm 2014), nftables hiện là mặc định trong Debian 10+, RHEL 8+ và Fedora 32+. Mọi bản phân phối lớn đều đã cam kết sử dụng nó.
Bắt Đầu Với Nftables
Trên hầu hết các bản phân phối hiện đại, nftables đã được cài sẵn. Kiểm tra trạng thái hiện tại:
nft list ruleset
Output rỗng nghĩa là bộ rule đang trống — bạn bắt đầu từ đầu. Đang migrate từ iptables? Dùng công cụ dịch chuyển:
# Chuyển đổi các rule iptables hiện có sang cú pháp nftables
iptables-save | iptables-translate > /tmp/nftables-migrated.nft
ip6tables-save | ip6tables-translate >> /tmp/nftables-migrated.nft
# Kiểm tra trước khi áp dụng
cat /tmp/nftables-migrated.nft
Cấu Trúc Bộ Rule Cơ Bản
Nftables tổ chức rule thành các table chứa các chain. Khác với iptables — nơi các table được cố định là filter, nat và mangle — nftables cho phép bạn đặt tên table tùy ý và chọn address family một cách tường minh.
# Tạo bảng inet đơn giản (xử lý cả IPv4 và IPv6)
nft add table inet main_firewall
# Thêm chain input với chính sách mặc định là drop
nft add chain inet main_firewall input { type filter hook input priority 0\; policy drop\; }
# Cho phép các kết nối đã thiết lập
nft add rule inet main_firewall input ct state established,related accept
# Cho phép loopback
nft add rule inet main_firewall input iif lo accept
# Cho phép SSH
nft add rule inet main_firewall input tcp dport 22 accept
# Cho phép HTTP và HTTPS
nft add rule inet main_firewall input tcp dport { 80, 443 } accept
Chú ý family inet — một chain xử lý đồng thời cả IPv4 lẫn IPv6. Thay đổi đơn giản này loại bỏ hoàn toàn lớp lỗi “quên cập nhật ip6tables”.
Sử Dụng File Cấu Hình
Các lệnh nft add riêng lẻ ổn cho việc thử nghiệm. Rule production nên nằm trong /etc/nftables.conf. Cú pháp gọn gàng hơn đáng kể so với bất cứ thứ gì iptables tạo ra:
#!/usr/sbin/nft -f
flush ruleset
table inet firewall {
# Chặn các IP xấu đã biết bằng set — không trùng lặp rule
set blocklist {
type ipv4_addr
flags interval
elements = { 192.168.100.0/24, 10.0.0.5 }
}
chain input {
type filter hook input priority 0; policy drop;
# Chặn ngay các IP trong danh sách
ip saddr @blocklist drop
ct state invalid drop
ct state { established, related } accept
iif "lo" accept
# ICMP — cho phép ping nhưng giới hạn tốc độ
ip protocol icmp icmp type echo-request limit rate 10/second accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH với giới hạn tốc độ kết nối (chống brute-force)
tcp dport 22 ct state new limit rate 5/minute accept
# Traffic web
tcp dport { 80, 443 } accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Áp dụng và làm cho nó persistent:
# Áp dụng bộ rule
nft -f /etc/nftables.conf
# Bật khi khởi động (systemd)
systemctl enable nftables
systemctl start nftables
# Kiểm tra
nft list ruleset
Cấu Hình NAT — Nơi Nftables Thực Sự Tỏa Sáng
Masquerade và chuyển tiếp port xuất hiện liên tục trên các server chạy container hoặc VM. Cấu hình NAT này xử lý cả DNAT lẫn masquerade trong một file — không cần lệnh ip6tables song song, không cần đồng bộ trạng thái thủ công giữa các công cụ:
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# Chuyển tiếp port 8080 trên host đến container nội bộ tại 172.16.0.10:80
tcp dport 8080 dnat to 172.16.0.10:80
}
chain postrouting {
type nat hook postrouting priority 100;
# Masquerade traffic đi ra qua eth0
oif "eth0" masquerade
}
}
Quy Trình Kiểm Tra Đã Cứu Tôi Hai Lần
Tải lại atomic là thật và hữu ích. Nhưng nó vẫn không ngăn bạn tự khóa mình ra ngoài nếu chính sách mới drop toàn bộ traffic inbound. Quy trình tiêu chuẩn của tôi trước khi đụng vào rule tường lửa trên bất kỳ server production nào:
# Lưu bộ rule đang hoạt động TRƯỚC TIÊN
nft list ruleset > /root/nft-backup-$(date +%Y%m%d-%H%M).conf
# Kiểm tra cú pháp mà không áp dụng
nft -c -f /etc/nftables.conf
# Lên lịch rollback tự động phòng khi mất kết nối
# (Chạy lệnh này TRƯỚC KHI áp dụng rule mới)
echo "nft flush ruleset && nft -f /root/nft-backup-*.conf" | at now + 5 minutes
# Áp dụng rule mới
nft -f /etc/nftables.conf
# Kiểm tra kết nối từ máy khác, SAU ĐÓ hủy lịch rollback
atrm $(atq | tail -1 | cut -f1)
Thủ thuật lệnh at đã cứu được hai server cho tôi — một lần do lỗi copy-paste khiến toàn bộ traffic SSH bị drop, một lần do chain forward cấu hình sai đã chặn mạng container. Năm phút là đủ thời gian để nhận ra vấn đề trước khi rollback được kích hoạt.
Migrate Các Server Production Của Bạn
Sáu tháng chạy nftables trên cả 12 server đã thay đổi hoàn toàn bức tranh bảo trì. Cập nhật rule chuyển từ việc phải sửa bốn file riêng biệt xuống còn chỉnh một file. Phạm vi bảo vệ IPv6 chuyển từ “chắc ổn” sang thực sự được đảm bảo. Thêm 50 IP vào blocklist trở thành một thao tác set duy nhất — không phải 50 rule được append làm chậm mỗi lần đánh giá gói tin tiếp theo.
Với hầu hết các server, quá trình migrate chỉ mất một buổi chiều: chạy iptables-translate để có điểm khởi đầu, dọn dẹp output (đủ dễ đọc để review trong dưới 10 phút), kiểm tra với bộ đếm rollback, rồi chuyển sang. Layer tương thích iptables vẫn sẵn có trên hầu hết các distro nếu bạn cần rollback thêm.
Debian, RHEL và Fedora đều đã cài nftables làm mặc định. Firewalld dùng nó như một backend. Docker đang tích cực phát triển hỗ trợ nftables native. Hệ sinh thái đã chuẩn hóa. Nếu bạn vẫn đang tự bảo trì rule iptables vào năm 2026, bạn đang gánh nợ kỹ thuật với hạ tầng mà các bản phân phối lớn đã bỏ lại phía sau.

