Tại Sao nftables Là Tường Lửa Bắt Buộc Trên Linux Năm 2026
Nếu bạn vẫn đang dùng iptables để quản lý tường lửa trên máy chủ Linux — thì nói thẳng, đây là lúc phải thay đổi. Không phải "nên", mà là phải. iptables đã chính thức bị Red Hat đánh dấu deprecated trong RHEL 9, và rất có thể sẽ bị loại bỏ hoàn toàn trong RHEL 10. Debian, Ubuntu, Fedora — tất cả đều đã chuyển sang nftables làm framework tường lửa mặc định rồi.
Chưa hết — Kubernetes 1.35 (phát hành tháng 12/2025) cũng đã chính thức deprecated chế độ IPVS trong kube-proxy và khuyến nghị chuyển sang nftables. Trong các bài benchmark với cluster chạy 30.000 Service, độ trễ worst-case (p99) của nftables thậm chí còn tốt hơn best-case (p01) của iptables. Đọc lại đi — worst-case tốt hơn best-case. Con số đó nói lên tất cả.
Nhưng hiệu năng chỉ là một phần câu chuyện thôi.
Với 5.530 CVE trên nhân Linux trong năm 2025 — tăng 28% so với năm trước — và Linux gánh gần 50% khối lượng công việc đám mây toàn cầu, một tường lửa được cấu hình đúng cách không còn là tùy chọn nữa. Nó là tuyến phòng thủ đầu tiên và quan trọng nhất của bạn.
Trong bài viết này, mình sẽ hướng dẫn bạn cấu hình nftables từ con số 0 — từ cài đặt, kiến trúc cơ bản, cho đến các kỹ thuật nâng cao như rate limiting, dynamic sets, tích hợp Fail2Ban, và cả việc chuyển đổi từ iptables. Tất cả đều kèm ví dụ thực tế, copy-paste được luôn.
nftables Là Gì Và Khác Gì So Với iptables
Kiến trúc hoàn toàn mới
Nhiều người lầm tưởng nftables chỉ là "iptables cải tiến" — nhưng không phải. Nó là một thiết kế lại hoàn toàn framework lọc gói tin trong nhân Linux, xuất hiện từ kernel 3.13 (năm 2014). Thay vì phải dùng đến 4 công cụ riêng biệt (iptables, ip6tables, arptables, ebtables), nftables gộp tất cả vào một công cụ dòng lệnh duy nhất: nft.
Bên trong kernel, nftables sử dụng một máy ảo (VM) chuyên biệt để thực thi bytecode, thay vì cơ chế khớp tuyến tính O(N) của iptables. Kết quả? Hiệu năng vượt trội, đặc biệt khi ruleset phình to lên hàng nghìn dòng.
So sánh nhanh nftables vs iptables
Mình tổng hợp lại những khác biệt chính để bạn dễ hình dung:
- Công cụ CLI: iptables cần 4 công cụ riêng biệt (iptables, ip6tables, arptables, ebtables) — nftables chỉ cần
nft - IPv4/IPv6: iptables xử lý riêng biệt — nftables thống nhất qua family
inet - Hiệu năng: iptables có độ phức tạp O(N) — nftables sử dụng hashtable và red-black tree, nhanh hơn đáng kể
- Table/chain mặc định: iptables có sẵn (INPUT, OUTPUT, FORWARD) — nftables bắt đầu từ trang trắng, bạn tự tạo
- Cập nhật nguyên tử: iptables thay thế toàn bộ ruleset mỗi lần cập nhật — nftables hỗ trợ cập nhật nguyên tử trong một giao dịch Netlink duy nhất
- Cấu trúc dữ liệu: iptables không có tích hợp sẵn — nftables có sets, maps, verdict maps tích hợp
- Global lock: iptables có global lock gây nghẽn cổ chai — nftables cho phép mỗi component có table riêng, không tranh chấp lock
Tại sao Kubernetes cũng chuyển sang nftables
Kubernetes 1.35 deprecated chế độ IPVS trong kube-proxy vì hai lý do chính: thiếu developer có chuyên môn sâu về IPVS và nftables đã chứng minh hiệu năng tương đương hoặc tốt hơn. SIG-Network quyết định hợp nhất nỗ lực phát triển thay vì duy trì ba backend riêng biệt (iptables, IPVS, nftables) — hợp lý thôi, ai mà muốn maintain ba codebase cho cùng một chức năng.
Điều đáng chú ý là API của nftables cho phép mỗi component có table riêng biệt, loại bỏ hoàn toàn vấn đề global lock contention — thứ đã cản trở iptables suốt nhiều năm. Microsoft Azure AKS cũng đã hỗ trợ preview chế độ nftables cho kube-proxy rồi.
Cài Đặt nftables Trên Các Bản Phân Phối Linux
Hầu hết các distro Linux hiện đại đã cài sẵn nftables. Nhưng nếu server của bạn chưa có, cài đặt chỉ mất vài giây.
Ubuntu/Debian
# Cài đặt nftables
sudo apt update && sudo apt install -y nftables
# Kích hoạt và khởi động dịch vụ
sudo systemctl enable nftables
sudo systemctl start nftables
# Kiểm tra trạng thái
sudo systemctl status nftables
# Kiểm tra phiên bản
nft --version
RHEL/CentOS/Fedora/AlmaLinux
# Cài đặt nftables
sudo dnf install -y nftables
# Kích hoạt và khởi động
sudo systemctl enable nftables
sudo systemctl start nftables
# Xác nhận iptables đang dùng nftables backend
sudo alternatives --display iptables
Arch Linux
# Cài đặt nftables
sudo pacman -S nftables
# Kích hoạt dịch vụ
sudo systemctl enable nftables
sudo systemctl start nftables
Lưu ý quan trọng: Trên các hệ thống đang chạy firewalld (như Fedora, RHEL), firewalld đã sử dụng nftables làm backend mặc định. Nếu bạn muốn quản lý nftables trực tiếp, hãy tắt firewalld trước — nếu không hai thằng sẽ "đánh nhau" và bạn sẽ rất đau đầu debug:
# Tắt firewalld nếu muốn dùng nftables trực tiếp
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl mask firewalld
Hiểu Kiến Trúc nftables: Table, Chain, Rule
Đây là phần quan trọng nhất, nên đọc kỹ nhé. Không giống iptables với các table/chain có sẵn, nftables bắt đầu từ một trang trắng hoàn toàn — bạn tự thiết kế mọi thứ từ đầu.
Ban đầu mình cũng thấy hơi bỡ ngỡ vì quen với INPUT, OUTPUT, FORWARD có sẵn của iptables. Nhưng sau khi dùng một thời gian thì phải thừa nhận — cách tiếp cận "trang trắng" này linh hoạt hơn rất nhiều.
Tables — Vùng chứa cao nhất
Table là container chứa chains và rules. Mỗi table thuộc một address family:
ip— Chỉ IPv4ip6— Chỉ IPv6inet— IPv4 + IPv6 gộp chung (khuyến nghị cho hầu hết trường hợp)arp— Gói ARPbridge— Frame ở tầng bridgenetdev— Lọc từ ingress (trước khi vào stack mạng)
Khuyến nghị: Trong đa số trường hợp, cứ dùng family inet là ổn nhất. Nó xử lý cả IPv4 và IPv6 trong cùng một ruleset — không phải viết rules hai lần như iptables nữa.
Chains — Nơi rules được thực thi
Chain chứa các rules và được gắn vào một hook trong kernel. Có hai loại:
- Base chain: Gắn trực tiếp vào hook (input, output, forward, prerouting, postrouting). Đây là điểm mà kernel "bắt" gói tin và chuyển cho nftables xử lý.
- Regular chain: Không gắn hook, được gọi từ base chain bằng lệnh
jumphoặcgoto— giống kiểu gọi hàm (function call) vậy.
Mỗi base chain có ba thuộc tính quan trọng:
chain input {
type filter hook input priority 0; policy drop;
# type: filter | nat | route
# hook: input | output | forward | prerouting | postrouting
# priority: số nguyên (số nhỏ hơn = ưu tiên cao hơn)
# policy: accept | drop (mặc định cho gói tin không khớp rule nào)
}
Rules — Điều kiện và hành động
Rule định nghĩa điều kiện khớp (match) và hành động (action). Cú pháp nftables trực quan hơn iptables nhiều — so sánh thử nhé:
# iptables (cú pháp cũ)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# nftables (cú pháp mới — rõ ràng hơn)
nft add rule inet filter input tcp dport 22 accept
Nhìn là thấy khác biệt đúng không? Cú pháp nftables đọc gần giống ngôn ngữ tự nhiên hơn hẳn.
Cấu Hình Tường Lửa Gia Cố Cho Server Linux
OK, giờ đến phần thực hành — phần mà mọi người mong đợi nhất. Dưới đây là cấu hình nftables hoàn chỉnh cho một máy chủ Linux production. Nguyên tắc vàng luôn là: từ chối tất cả theo mặc định, chỉ cho phép những gì thực sự cần thiết.
Cấu hình nền tảng — Web server với SSH
Tạo file cấu hình tại /etc/nftables.conf:
#!/usr/sbin/nft -f
# Xóa toàn bộ ruleset hiện tại để bắt đầu sạch
flush ruleset
# Định nghĩa biến cho dễ quản lý
define SSH_PORT = 22
define WEB_PORTS = { 80, 443 }
define TRUSTED_SSH = { 203.0.113.10, 198.51.100.0/24 }
table inet firewall {
# Chain xử lý traffic đến server
chain input {
type filter hook input priority 0; policy drop;
# Cho phép kết nối đã thiết lập và liên quan
ct state established,related accept
# Cho phép loopback (bắt buộc cho hoạt động nội bộ)
iif "lo" accept
# Loại bỏ gói tin trạng thái invalid
ct state invalid drop
# Cho phép ICMP cơ bản (ping, traceroute) với giới hạn tốc độ
ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded } limit rate 10/second accept
ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply, nd-neighbor-solicit, nd-neighbor-advert, nd-router-solicit, nd-router-advert } limit rate 10/second accept
# SSH — chỉ cho phép từ IP tin cậy
tcp dport $SSH_PORT ip saddr $TRUSTED_SSH ct state new accept
# HTTP và HTTPS — cho phép từ mọi nơi
tcp dport $WEB_PORTS ct state new accept
# Ghi log các gói tin bị từ chối (giới hạn để tránh log flood)
limit rate 5/minute log prefix "nftables-drop-input: " counter drop
}
# Chain xử lý traffic chuyển tiếp (tắt nếu không cần)
chain forward {
type filter hook forward priority 0; policy drop;
}
# Chain xử lý traffic đi ra
chain output {
type filter hook output priority 0; policy accept;
# Cho phép loopback
oif "lo" accept
# Cho phép kết nối đã thiết lập
ct state established,related accept
# Cho phép DNS, NTP, HTTPS ra ngoài
tcp dport { 53, 443 } accept
udp dport { 53, 123 } accept
# Nếu muốn gia cố output chặt hơn, đổi policy thành drop
# và chỉ cho phép những kết nối cần thiết
}
}
Áp dụng và kiểm tra cấu hình
# Kiểm tra cú pháp TRƯỚC KHI áp dụng (rất quan trọng!)
sudo nft -c -f /etc/nftables.conf
# Nếu không có lỗi, áp dụng cấu hình
sudo nft -f /etc/nftables.conf
# Xác nhận ruleset đã được tải
sudo nft list ruleset
# Xem chi tiết một chain cụ thể
sudo nft list chain inet firewall input
Cảnh báo quan trọng: Luôn kiểm tra cú pháp bằng nft -c trước khi áp dụng. nftables áp dụng ruleset theo kiểu nguyên tử (atomic) — nếu có lỗi cú pháp, không rule nào được áp dụng cả, nên về mặt đó thì khá an toàn. Tuy nhiên, nếu bạn quên cho phép SSH trước khi đổi policy thành drop... thì chúc mừng, bạn vừa tự khóa mình ra khỏi server. Mình đã thấy chuyện này xảy ra không ít lần.
Mẹo an toàn: Tự động rollback
Nếu bạn đang cấu hình từ xa qua SSH (mà đa phần là vậy), hãy dùng kỹ thuật "dead man switch" để tự động khôi phục cấu hình cũ nếu có sự cố. Nghiêm túc mà nói, đây là thói quen nên có:
# Sao lưu cấu hình hiện tại
sudo nft list ruleset > /tmp/nftables-backup.conf
# Đặt lệnh tự động khôi phục sau 2 phút
sudo at now + 2 minutes <<RESTORE
nft -f /tmp/nftables-backup.conf
RESTORE
# Áp dụng cấu hình mới
sudo nft -f /etc/nftables.conf
# Nếu mọi thứ ổn, hủy lệnh khôi phục
sudo atrm $(atq | awk '{print $1}')
Ý tưởng đơn giản lắm: nếu sau 2 phút bạn không hủy lệnh rollback (vì bị khóa ngoài chẳng hạn), hệ thống sẽ tự quay lại cấu hình cũ. Cứu mạng đấy.
Kỹ Thuật Nâng Cao: Sets, Maps Và Rate Limiting
Đây là nơi nftables thực sự tỏa sáng so với iptables. Nói thật, khi mới tìm hiểu phần này mình khá bất ngờ vì sets và maps giúp viết ruleset ngắn gọn và hiệu quả hơn rất nhiều.
Named sets — Danh sách IP động
Named sets cho phép bạn tạo danh sách IP có thể cập nhật động mà không cần tải lại toàn bộ ruleset. Đây là tính năng mà iptables không có tương đương trực tiếp (phải dùng ipset bên ngoài):
table inet firewall {
# Set chứa các IP bị chặn
set blocklist {
type ipv4_addr
flags timeout
# Mỗi phần tử tự động hết hạn sau 24 giờ
timeout 24h
}
# Set chứa các IP tin cậy
set trusted_ips {
type ipv4_addr
elements = { 203.0.113.10, 198.51.100.20, 192.0.2.30 }
}
chain input {
type filter hook input priority 0; policy drop;
# Chặn ngay các IP trong blocklist
ip saddr @blocklist drop
# Cho phép SSH chỉ từ IP tin cậy
tcp dport 22 ip saddr @trusted_ips accept
# ... các rules khác
}
}
Quản lý set từ dòng lệnh cũng rất dễ:
# Thêm IP vào blocklist (tự hết hạn sau 24h)
sudo nft add element inet firewall blocklist { 192.168.1.100 timeout 24h }
# Thêm nhiều IP cùng lúc
sudo nft add element inet firewall blocklist { 10.0.0.5, 10.0.0.6, 10.0.0.7 }
# Xóa IP khỏi blocklist
sudo nft delete element inet firewall blocklist { 192.168.1.100 }
# Xem nội dung set
sudo nft list set inet firewall blocklist
# Thêm IP vào trusted_ips
sudo nft add element inet firewall trusted_ips { 172.16.0.50 }
Verdict maps — Quyết định khác nhau cho từng trường hợp
Verdict maps cho phép bạn ánh xạ giá trị đến hành động cụ thể — cực kỳ hữu ích khi cần xử lý nhiều port với logic khác nhau. Thay vì viết hàng chục rule riêng lẻ, bạn gom vào một map gọn gàng:
table inet firewall {
# Map ánh xạ port đến chain xử lý riêng
map port_policy {
type inet_service : verdict
elements = {
22 : jump ssh_filter,
80 : accept,
443 : accept,
3306 : jump db_filter,
}
}
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
# Dùng verdict map để phân luồng xử lý
tcp dport vmap @port_policy
}
chain ssh_filter {
# Giới hạn SSH từ các subnet cụ thể
ip saddr 10.0.0.0/8 accept
ip saddr 172.16.0.0/12 accept
drop
}
chain db_filter {
# Database chỉ cho phép từ app servers
ip saddr { 10.0.1.10, 10.0.1.11, 10.0.1.12 } accept
drop
}
}
Rate limiting — Chống brute-force và DDoS
Rate limiting có lẽ là tính năng bảo mật mạnh nhất của nftables cho việc bảo vệ server. Có nhiều cách tiếp cận, từ đơn giản đến nâng cao — tùy mức độ bạn cần.
Cách 1: Giới hạn đơn giản theo tốc độ toàn cục
# Giới hạn 15 kết nối SSH mới mỗi phút (toàn cục)
tcp dport 22 ct state new limit rate 15/minute accept comment "Chong brute-force SSH"
Cách này nhanh gọn nhưng có nhược điểm: giới hạn áp dụng cho tất cả mọi người. Nếu có 15 người dùng hợp lệ kết nối cùng lúc, người thứ 16 sẽ bị chặn dù không làm gì sai.
Cách 2: Giới hạn theo từng IP nguồn (khuyến nghị)
table inet firewall {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
# Giới hạn mỗi IP chỉ được 5 kết nối SSH mới trong 1 phút
tcp dport 22 ct state new meter ssh_ratelimit { ip saddr limit rate 5/minute } accept
# Gói tin vượt quá giới hạn sẽ bị drop (vì policy drop)
}
}
Cách 3: Tự động chặn IP brute-force bằng dynamic sets (không cần Fail2Ban)
Đây là kỹ thuật mình thích nhất — nftables tự động phát hiện và chặn IP đang tấn công brute-force mà không cần bất kỳ daemon bên ngoài nào:
table inet firewall {
# Set lưu các IP bị chặn tạm thời
set ssh_banned {
type ipv4_addr
flags dynamic, timeout
timeout 2h
}
# Set theo dõi tốc độ kết nối
set ssh_conntrack {
type ipv4_addr
flags dynamic, timeout
timeout 1m
}
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
# Chặn ngay các IP đã bị ban
ip saddr @ssh_banned drop
# Nếu IP tạo quá 10 kết nối SSH/phút → thêm vào ban list 2 giờ
tcp dport 22 ct state new add @ssh_conntrack { ip saddr limit rate over 10/minute } add @ssh_banned { ip saddr timeout 2h } drop
# Cho phép SSH bình thường
tcp dport 22 ct state new accept
# Các rules khác...
tcp dport { 80, 443 } accept
}
}
Logic ở đây khá hay: nếu một IP gửi hơn 10 yêu cầu kết nối SSH trong 1 phút, nó tự động bị chặn trong 2 giờ. Sau 2 giờ, phần tử hết hạn và IP có thể kết nối lại. Không cần cron job, không cần daemon bổ sung — tất cả xử lý trong kernel.
Tích Hợp nftables Với Fail2Ban — Bảo Vệ Đa Lớp
Dù nftables có thể tự xử lý rate limiting như ở trên, mình vẫn khuyến nghị kết hợp với Fail2Ban. Lý do? Fail2Ban phân tích log xác thực thực tế — nó chặn IP dựa trên số lần đăng nhập thất bại, chứ không chỉ đếm số kết nối. Chính xác hơn nhiều trong thực tế.
Kết hợp cả hai tạo ra hệ thống phòng thủ đa lớp mạnh hơn hẳn.
Bước 1: Tạo table nftables cho Fail2Ban
Tạo file /etc/nftables/fail2ban.conf:
#!/usr/sbin/nft -f
table ip fail2ban {
chain input {
type filter hook input priority 100;
}
}
Thêm vào file cấu hình chính /etc/nftables.conf (sau dòng flush ruleset):
flush ruleset
include "/etc/nftables/fail2ban.conf"
# ... phần còn lại của cấu hình firewall
Bước 2: Cấu hình Fail2Ban sử dụng nftables
Tạo file /etc/fail2ban/jail.local:
[DEFAULT]
# Sử dụng nftables thay vì iptables
banaction = nftables-multiport
banaction_allports = nftables-allports
chain = input
# Cấu hình chung
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
port = ssh
backend = systemd
maxretry = 3
bantime = 2h
# Jail cho recidive (chặn lâu hơn nếu tái phạm)
[recidive]
enabled = true
banaction = nftables-allports
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 3
Phần [recidive] là chi tiết nhỏ nhưng quan trọng — nếu một IP bị ban rồi lại quay lại tấn công, nó sẽ bị chặn luôn 1 tuần. Đủ để hầu hết bot tự bỏ cuộc.
Bước 3: Cấu hình action nftables
Tạo file /etc/fail2ban/action.d/nftables-common.local:
[Init]
# Sử dụng family ip
nftables_family = ip
nftables_table = fail2ban
# Drop thay vì reject (không tiết lộ thông tin cho attacker)
blocktype = drop
# Xóa prefix để tránh giới hạn 15 ký tự tên set
nftables_set_prefix =
Bước 4: Đảm bảo Fail2Ban khởi động lại khi nftables reload
Đây là bước nhiều người hay quên. Nếu nftables được reload mà Fail2Ban không restart theo, các rules chặn IP sẽ bị mất. Tạo override cho systemd để xử lý:
# Tạo thư mục override
sudo mkdir -p /etc/systemd/system/fail2ban.service.d
# Tạo file override
cat <<EOF | sudo tee /etc/systemd/system/fail2ban.service.d/nftables.conf
[Unit]
Requires=nftables.service
PartOf=nftables.service
After=nftables.service
EOF
# Tải lại systemd và khởi động lại Fail2Ban
sudo systemctl daemon-reload
sudo systemctl restart fail2ban
# Kiểm tra trạng thái
sudo fail2ban-client status sshd
Giờ thì mỗi khi nftables được khởi động lại hoặc reload, Fail2Ban cũng sẽ tự động restart và tạo lại các rules chặn IP.
Chuyển Đổi Từ iptables Sang nftables
Nếu bạn đang có hệ thống chạy iptables và muốn chuyển sang nftables, tin tốt là có công cụ hỗ trợ chuyển đổi tự động. Không cần viết lại từ đầu.
Sử dụng iptables-translate
Công cụ iptables-translate chuyển đổi từng rule từ cú pháp iptables sang nftables:
# Chuyển đổi từng rule
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# Kết quả: nft add rule ip filter INPUT tcp dport 22 counter accept
iptables-translate -A INPUT -s 192.168.1.0/24 -p tcp --dport 80 -j ACCEPT
# Kết quả: nft add rule ip filter INPUT ip saddr 192.168.1.0/24 tcp dport 80 counter accept
# Chuyển đổi rule có rate limiting
iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
# Kết quả sẽ hiển thị cú pháp nftables tương đương
Xuất toàn bộ ruleset iptables sang nftables
# Lưu ruleset iptables hiện tại
sudo iptables-save > /tmp/iptables-rules.txt
# Chuyển đổi toàn bộ ruleset
sudo iptables-restore-translate -f /tmp/iptables-rules.txt > /tmp/nftables-rules.nft
# Xem kết quả chuyển đổi
cat /tmp/nftables-rules.nft
# Kiểm tra cú pháp
sudo nft -c -f /tmp/nftables-rules.nft
# Nếu OK, áp dụng
sudo nft -f /tmp/nftables-rules.nft
Lưu ý: Công cụ chuyển đổi tự động hoạt động tốt cho rules đơn giản. Tuy nhiên, với cấu hình phức tạp — đặc biệt rules dùng module -m string cho DPI — bạn sẽ cần viết lại thủ công. nftables không hỗ trợ trực tiếp string match (DPI) như iptables, nên nếu cần DPI thì hãy dùng IPS bổ sung như Suricata.
Quy trình chuyển đổi an toàn cho production
Đây là quy trình mình khuyến nghị cho server production — cẩn thận không bao giờ thừa:
# 1. Sao lưu toàn bộ cấu hình iptables hiện tại
sudo iptables-save > /root/iptables-backup-$(date +%Y%m%d).txt
# 2. Chuyển đổi và chỉnh sửa ruleset nftables
sudo iptables-restore-translate -f /root/iptables-backup-*.txt > /etc/nftables.conf
# 3. Kiểm tra cú pháp
sudo nft -c -f /etc/nftables.conf
# 4. Đặt dead man switch (tự khôi phục sau 3 phút)
sudo at now + 3 minutes <<ROLLBACK
iptables-restore < /root/iptables-backup-*.txt
systemctl stop nftables
ROLLBACK
# 5. Áp dụng nftables và kiểm tra kết nối
sudo nft -f /etc/nftables.conf
# 6. Kiểm tra: SSH vẫn hoạt động? Web server phản hồi? API endpoint OK?
# 7. Nếu mọi thứ ổn, hủy rollback và tắt iptables
sudo atrm $(atq | awk '{print $1}')
sudo systemctl disable iptables 2>/dev/null
sudo systemctl enable nftables
Cấu Hình NAT Và Port Forwarding Với nftables
Nếu server của bạn hoạt động như gateway hoặc router, bạn sẽ cần cấu hình NAT. Tin vui là nftables xử lý NAT đơn giản và rõ ràng hơn iptables.
Source NAT (SNAT/Masquerade) — Chia sẻ kết nối Internet
table ip nat {
chain postrouting {
type nat hook postrouting priority 100;
# Masquerade cho traffic từ mạng nội bộ đi ra Internet
ip saddr 10.0.0.0/24 oif "eth0" masquerade
# Hoặc SNAT với IP cố định (hiệu năng tốt hơn masquerade)
# ip saddr 10.0.0.0/24 oif "eth0" snat to 203.0.113.1
}
}
# Đừng quên bật IP forwarding trong kernel
# echo 1 > /proc/sys/net/ipv4/ip_forward
# Hoặc thêm vào /etc/sysctl.conf:
# net.ipv4.ip_forward = 1
Mẹo nhỏ: nếu server có IP tĩnh, dùng snat to thay vì masquerade — hiệu năng sẽ tốt hơn vì kernel không cần tra cứu IP mỗi gói tin.
Destination NAT (DNAT) — Port forwarding
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# Chuyển tiếp port 8080 bên ngoài đến web server nội bộ port 80
tcp dport 8080 dnat to 10.0.0.100:80
# Chuyển tiếp port 2222 đến SSH server nội bộ
tcp dport 2222 dnat to 10.0.0.50:22
}
}
# Cũng cần cho phép forward trong chain forward
table inet firewall {
chain forward {
type filter hook forward priority 0; policy drop;
# Cho phép forward đến các dịch vụ NAT
ct state established,related accept
ip daddr 10.0.0.100 tcp dport 80 accept
ip daddr 10.0.0.50 tcp dport 22 accept
}
}
Giám Sát Và Debug Tường Lửa nftables
Cấu hình xong chưa phải là hết — thực ra mới chỉ là bắt đầu thôi. Bạn cần giám sát liên tục để phát hiện vấn đề sớm và tối ưu rules khi cần.
Xem counter và thống kê
# Xem toàn bộ ruleset kèm counter
sudo nft list ruleset
# Xem counter cho một chain cụ thể
sudo nft list chain inet firewall input
# Theo dõi thay đổi realtime
watch -n 2 'sudo nft list chain inet firewall input'
# Reset counter
sudo nft reset counters
Packet tracing — Debug rules không hoạt động
Khi một rule không hoạt động như mong đợi (và tin mình đi, chuyện này sẽ xảy ra), packet tracing là công cụ debug tốt nhất:
# Bật tracing cho traffic SSH đến
sudo nft add rule inet firewall input tcp dport 22 meta nftrace set 1
# Bắt đầu theo dõi trace
sudo nft monitor trace
# Bạn sẽ thấy chi tiết gói tin đi qua từng rule như thế nào
# Nhớ xóa rule trace sau khi debug xong để tránh ảnh hưởng hiệu năng
sudo nft flush chain inet firewall input
sudo nft -f /etc/nftables.conf
Logging thông minh — Tránh log flood
# Log gói tin bị drop với prefix rõ ràng và giới hạn tốc độ
chain input {
type filter hook input priority 0; policy drop;
# ... các accept rules ở trên ...
# Log TCP drops
tcp flags syn limit rate 5/minute log prefix "nft-tcp-drop: " counter drop
# Log UDP drops
udp limit rate 5/minute log prefix "nft-udp-drop: " counter drop
# Drop phần còn lại không cần log
counter drop
}
Logs sẽ xuất hiện trong /var/log/kern.log hoặc bạn có thể xem qua journalctl:
# Theo dõi log nftables realtime
sudo journalctl -k -f | grep "nft-"
# Hoặc dùng dmesg
sudo dmesg -w | grep "nft-"
Các Lệnh nftables Thường Dùng — Cheat Sheet
Lưu lại trang này nhé — dưới đây là danh sách các lệnh bạn sẽ dùng thường xuyên khi làm việc với nftables:
# === QUẢN LÝ RULESET ===
sudo nft list ruleset # Xem toàn bộ rules
sudo nft list tables # Liệt kê các tables
sudo nft list table inet firewall # Xem chi tiết một table
sudo nft list chain inet firewall input # Xem chi tiết một chain
sudo nft list set inet firewall blocklist # Xem nội dung một set
# === KIỂM TRA VÀ ÁP DỤNG ===
sudo nft -c -f /etc/nftables.conf # Kiểm tra cú pháp (không áp dụng)
sudo nft -f /etc/nftables.conf # Tải cấu hình từ file
sudo nft flush ruleset # Xóa toàn bộ rules (NGUY HIỂM!)
# === QUẢN LÝ SETS ===
sudo nft add element inet firewall blocklist { 1.2.3.4 } # Thêm IP
sudo nft add element inet firewall blocklist { 1.2.3.4 timeout 1h } # Thêm IP tạm thời
sudo nft delete element inet firewall blocklist { 1.2.3.4 } # Xóa IP
# === THÊM/XÓA RULES NHANH ===
sudo nft add rule inet firewall input tcp dport 8080 accept # Thêm rule cuối chain
sudo nft insert rule inet firewall input tcp dport 8080 accept # Thêm rule đầu chain
# === BACKUP VÀ RESTORE ===
sudo nft list ruleset > /root/nftables-backup.conf # Sao lưu
sudo nft -f /root/nftables-backup.conf # Khôi phục
# === DEBUG ===
sudo nft monitor # Theo dõi thay đổi ruleset
sudo nft monitor trace # Theo dõi packet trace
Best Practices — Những Điều Nên Và Không Nên Làm
Nên làm
- Luôn dùng policy drop cho chain input: Nguyên tắc default-deny là nền tảng của mọi cấu hình tường lửa an toàn
- Dùng family inet thay vì ip: Xử lý cả IPv4 và IPv6 trong cùng ruleset, tránh bỏ sót IPv6
- Kiểm tra cú pháp trước khi áp dụng: Luôn chạy
nft -c -ftrướcnft -f— đây là thói quen cứu mạng - Sao lưu trước mỗi thay đổi:
nft list ruleset > backup.conf— chỉ mất 1 giây nhưng cứu bạn khỏi bao rắc rối - Dùng biến (
define) cho IP và port: Dễ đọc, dễ bảo trì, ít lỗi hơn nhiều - Giới hạn tốc độ log: Tránh log flood làm đầy disk và ảnh hưởng hiệu năng
- Drop gói tin invalid sớm:
ct state invalid drop— loại bỏ gói tin bất thường ngay từ đầu chain
Không nên làm
- Không dùng
flush rulesettrên server remote: Nó xóa mọi rules, bao gồm cả rule cho phép SSH. Bạn sẽ bị khóa ngoài ngay lập tức - Không chạy iptables song song với nftables: Hai framework có thể xung đột với nhau. Chọn một thôi và tắt cái còn lại
- Không quên IPv6: Nếu dùng family
ip(chỉ IPv4), attacker có thể bypass qua IPv6. Dùnginethoặc cấu hình riêng choip6 - Không đặt policy accept cho chain input: Điều này nghĩa là mọi traffic đều được cho phép trừ khi bị chặn rõ ràng — rất nguy hiểm nếu bạn quên một rule nào đó
- Không tin tưởng port 443 là an toàn: Kẻ tấn công hoàn toàn có thể tunnel reverse shell qua HTTPS hoặc DNS. nftables lọc ở tầng L3/L4, không phải L7 — nếu cần DPI, hãy dùng thêm IPS như Suricata
Câu Hỏi Thường Gặp (FAQ)
nftables có thay thế hoàn toàn iptables không?
Có. nftables được thiết kế để thay thế hoàn toàn iptables, ip6tables, arptables và ebtables. Các bản phân phối lớn như Debian (từ Buster), Fedora, RHEL 9 và Ubuntu đều đã chuyển sang nftables làm mặc định. Red Hat đã deprecated iptables trong RHEL 9 và có thể loại bỏ trong RHEL 10. Tuy nhiên, iptables vẫn dùng được qua lớp tương thích iptables-nft — bạn gõ lệnh iptables nhưng bên dưới nó được chuyển thành nftables rules.
Tôi có cần cài đặt thêm gì ngoài nftables không?
nftables là lớp bảo vệ ở tầng mạng (L3/L4) — quan trọng, nhưng chưa đủ. Bạn nên kết hợp thêm: Fail2Ban để chặn IP dựa trên log xác thực, SSH hardening (tắt đăng nhập root, dùng key thay password), và nếu chạy web server thì cần WAF hoặc IPS như Suricata cho lọc tầng ứng dụng (L7). Tường lửa chỉ là một lớp trong chiến lược defense-in-depth mà thôi.
Làm thế nào để kiểm tra nftables có đang hoạt động không?
Đơn giản nhất: chạy sudo nft list ruleset. Nếu kết quả trả về các table và chain, nftables đang hoạt động. Nếu trống, chưa có ruleset nào được tải. Bạn cũng có thể kiểm tra dịch vụ bằng sudo systemctl status nftables và xem phiên bản bằng nft --version.
nftables có hoạt động với Docker và Kubernetes không?
Có, nhưng cần lưu ý vài điểm. Docker mặc định vẫn tạo rules qua iptables (với backend nft). Khi bạn cấu hình nftables trực tiếp, tuyệt đối không dùng flush ruleset vì nó sẽ xóa luôn cả rules của Docker. Về Kubernetes, từ phiên bản 1.31 kube-proxy đã hỗ trợ nftables mode (GA từ 1.33), và 1.35 đã deprecated IPVS mode. Nếu bạn đang dùng Kubernetes, hãy chuyển kube-proxy sang chế độ nftables.
Tôi nên dùng nftables trực tiếp hay qua firewalld/UFW?
Tùy nhu cầu. firewalld (trên RHEL/Fedora) và UFW (trên Ubuntu) là frontend dễ dùng hơn, và cả hai đều sử dụng nftables làm backend rồi. Nếu bạn chỉ cần cấu hình đơn giản (mở/đóng port), dùng firewalld hoặc UFW là đủ. Nhưng nếu bạn cần sets/maps, rate limiting nâng cao, verdict maps, hay cấu hình NAT phức tạp — thì dùng nftables trực tiếp sẽ linh hoạt hơn rất nhiều. Điều quan trọng nhất: không chạy cả hai cùng lúc để tránh xung đột rules.