Firewall là policy trên kernel networking

Linux dùng netfilter framework; iptablesnftables là frontend (nftables là hướng hiện đại). ufw là lớp “dễ nói chuyện” trên Debian/Ubuntu, vẫn sinh ra nft/iptables bên dưới.

command -v nft iptables ufw
sudo nft list ruleset 2>/dev/null | head
sudo iptables-save 2>/dev/null | head
sudo ufw status verbose 2>/dev/null

Default deny inbound, “đóng cửa trước khi treo tranh”

Inbound policy DROP nghĩa là: không có rule explicit ACCEPT → packet bị loại (thường timeout phía client nếu DROP tuyệt đối).

Anti-lockout: khi chỉnh SSH qua remote, luôn:

  1. Mở session thứ hai (mosh/tmux) hoặc console serial.
  2. iptables-restore / nft -f từ file đã test trên staging.
  3. Dùng at/sleep rollback nếu không ping được (pattern cứu nguy).

Stateful filter và conntrack

Nhiều rule cho phép ESTABLISHED,RELATED, dựa trên connection tracking. conntrack table đầy có thể gây hành vi lạ, bài observability mạng nói thêm; ở đây chỉ cần biết: firewall không chỉ là ACL tĩnh.


nftables tối giản: policy drop + allowlist port cụ thể

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    iif lo accept
    ct state established,related accept
    tcp dport 22 accept
    tcp dport 80 accept
    tcp dport 443 accept
    # ICMP có chọn lọc, tuỳ policy
    ip protocol icmp accept
    ip6 nexthdr ipv6-icmp accept
  }
}

Ghi chú IPv6: nếu bạn chỉ lock IPv4 nhưng host có AAAA và service listen [::], traffic có thể đi IPv6 và vượt rule IPv4-only một cách tinh vi.


ufw thực dụng

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status numbered

Allow theo app profile (OpenSSH) tiện vì đọc port từ /etc/services + package, nhưng app custom vẫn nên allow theo port + protocol rõ ràng.


Kiểm chứng rule: ss trước, tcpdump sau

  1. ss -lntp, process có listen không?
  2. curl từ máy khác, timeout vs refused (xem loạt Network).
  3. tcpdump có filter ngắn trên interface đúng, đừng dump toàn bộ production traffic lên disk.
sudo ss -lntp sport = :443

Docker và firewall: một lớp phức tạp

Published port có thể đi qua DOCKER chain / nft hook riêng, rule ufw trên INPUT đôi khi không đúng chỗ bạn nghĩ. Khi debug: vẽ diagram path packet (host → DNAT → container).


Lab an toàn: đổi firewall mà không tự khoá SSH

Trước khi apply rule mới trên server remote, mình luôn mở một session SSH thứ hai và chuẩn bị rollback timer:

sudo ss -ltnp
sudo nft list ruleset
sudo systemd-run --on-active=2m --unit rollback-fw -- /usr/sbin/ufw disable
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw enable

Nếu rule mới làm rớt SSH, timer sẽ tự tắt ufw sau 2 phút. Khi đã xác nhận SSH và HTTP còn sống từ bên ngoài, hủy rollback:

sudo systemctl cancel rollback-fw.service

Firewall là chỗ rất đáng cẩn thận. Một rule sai có thể biến maintenance 5 phút thành ticket “ai có console cloud không?”.


Liên hệ bài trước / sau


Câu hỏi hay gặp

1. “DROP vs REJECT?”
REJECT trả ICMP/port-unreachable, tiện debug nhưng lộ thông tin và có thể bị dùng để probe; DROP im lặng hơn nhưng client chờ timeout.

2. “Tôi mở port 443 nhưng vẫn timeout?”
Cloud SG/NACL, LB health path, hoặc IPv6 path khác IPv4, kiểm tra cả hai stack.

3. “nftables vs iptables-nft?”
Nhiều distro đã migration; đọc doc distro, tránh mix tool sinh rule conflict.


Bài tiếp theo trong loạt

Phần 10: SSH, vận hành và hardening, biên remote đúng nghĩa đen.