Tình huống quen thuộc: bạn được yêu cầu bổ sung firewall vào giữa router và switch của một hệ thống đang chạy ổn định. Khách hàng không cho phép thay đổi bất kỳ địa chỉ IP nào, không được đổi gateway trên các máy chủ. Đây là bài toán mà nhiều sysadmin gặp phải — và transparent firewall chính là câu trả lời.
Vấn đề thực tế: Cắm firewall vào mà không “phá” topology
Mình từng gặp case như này: một hệ thống production với ~50 máy chủ đang dùng dải 192.168.10.0/24, gateway là 192.168.10.1 (router của khách hàng). Yêu cầu là phải kiểm soát traffic giữa các nhóm máy chủ, lọc một số protocol nguy hiểm, nhưng tuyệt đối không được đổi IP hay cấu hình lại bất kỳ thiết bị nào đang chạy.
Firewall truyền thống hoạt động ở Layer 3 — nó nhận packet, xử lý routing, rồi forward. Điều này có nghĩa là bạn phải đổi gateway của tất cả máy trong mạng sang IP của firewall. Với 50 máy chủ production? Không ai dám làm vào giờ hành chính, chưa kể rủi ro downtime và thời gian rollback nếu có sự cố.
Phân tích nguyên nhân: Tại sao firewall thông thường không phù hợp
Vấn đề nằm ở chỗ firewall Layer 3 (routing-based) bắt buộc bạn phải thay đổi topology:
- Phải có 2 IP khác nhau trên 2 interface (một phía LAN, một phía uplink)
- Tất cả thiết bị trong mạng phải đổi default gateway sang IP của firewall
- DNS, monitoring, backup — tất cả đều phụ thuộc vào gateway cũ sẽ bị ảnh hưởng dây chuyền
Bridge firewall (transparent firewall) hoạt động ở Layer 2 — nó “trong suốt” như một switch thông thường. Từ góc nhìn của các máy trong mạng, firewall này không tồn tại. Packet đi qua nó mà không cần biết nó ở đó.
Về mặt kỹ thuật, khi bạn tạo một Linux bridge, kernel chuyển tiếp Ethernet frame giữa các interface thành viên mà không thay đổi địa chỉ MAC hay IP. nftables có khả năng hook vào bridge netfilter để kiểm tra và lọc các frame này trước khi chúng được forward.
Các cách giải quyết
Cách 1: ebtables (cũ, không khuyến nghị)
ebtables là công cụ lọc packet ở bridge layer từ thời iptables. Cú pháp phức tạp, không unified với iptables/ip6tables, và đang dần bị deprecated. Mình đã dùng nó vài năm trước và không có gì tệ hơn việc phải maintain 3 bộ rule riêng biệt cho IPv4, IPv6 và bridge.
Cách 2: iptables + physdev module
Dùng iptables với module physdev để match packet đi qua bridge. Cách này hoạt động được nhưng cần bật nhiều sysctl phức tạp và cú pháp khó nhớ, dễ sai:
# Cách cũ với iptables physdev — không khuyến nghị
iptables -I FORWARD -m physdev --physdev-in eth1 --physdev-out eth2 \
-p tcp --dport 22 -j ACCEPT
Cách 3: nftables bridge (hiện đại, khuyến nghị)
nftables hỗ trợ native bridge filtering từ kernel 4.17+. Một ruleset duy nhất có thể xử lý cả IPv4, IPv6 và Ethernet frame. Đây là cách mình đang dùng trên tất cả hệ thống mới triển khai.
Cách tốt nhất: Triển khai Transparent Firewall với nftables
Bước 1: Chuẩn bị hệ thống
Máy chủ Linux cần ít nhất 2 interface mạng (ví dụ: eth0 kết nối vào router/uplink, eth1 kết nối vào switch LAN nội bộ). Kiểm tra kernel version và load module cần thiết:
# Kiểm tra kernel version (cần >= 4.17 cho nftables bridge support)
uname -r
# Load module bridge netfilter
modprobe br_netfilter
modprobe nft_bridge_meta
# Kiểm tra module đã load chưa
lsmod | grep -E "br_netfilter|nft_bridge"
Bước 2: Tạo Linux Bridge
Tạo bridge và thêm 2 interface vào. Bridge không nhất thiết cần IP — nhưng nếu muốn SSH vào firewall để quản lý thì nên gán IP management:
# Tạo bridge br0
ip link add name br0 type bridge
# Thêm các interface thành viên vào bridge
ip link set eth0 master br0
ip link set eth1 master br0
# Bật tất cả interface
ip link set eth0 up
ip link set eth1 up
ip link set br0 up
# (Tùy chọn) Gán IP management nếu cần SSH vào firewall
ip addr add 192.168.10.254/24 dev br0
# Tắt STP nếu topology không có loop (tránh delay 30s khi khởi động)
ip link set br0 type bridge stp_state 0
Để persistent sau reboot, cấu hình qua Netplan (Ubuntu 22.04+):
# /etc/netplan/01-bridge.yaml
network:
version: 2
ethernets:
eth0:
dhcp4: false
eth1:
dhcp4: false
bridges:
br0:
interfaces: [eth0, eth1]
addresses: [192.168.10.254/24]
dhcp4: false
parameters:
stp: false
netplan apply
Bước 3: Bật sysctl cho bridge netfilter
Đây là bước hay bị bỏ sót nhất. Mặc định, kernel không pass bridge traffic qua netfilter. Phải bật explicitly, không thì viết rule nào cũng vô nghĩa:
cat > /etc/sysctl.d/99-bridge-firewall.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-arptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
Bước 4: Viết ruleset nftables
Đây là phần cốt lõi. nftables bridge family lọc ở Layer 2 (Ethernet frame), còn ip/ip6 family lọc ở Layer 3 (IP packet đi qua bridge):
cat > /etc/nftables.conf << 'EOF'
#!/usr/sbin/nft -f
flush ruleset
# Bridge table — lọc ở Layer 2 (Ethernet frame)
table bridge filter {
chain forward {
type filter hook forward priority filter; policy accept;
# Chặn VLAN tag không mong muốn (802.1Q)
ether type 0x8100 counter drop comment "Block unexpected VLAN tags"
# Log ARP để phát hiện ARP spoofing
ether type arp counter log prefix "ARP: "
}
}
# IP table — lọc ở Layer 3
table ip filter {
chain forward {
type filter hook forward priority filter; policy drop;
# Cho phép established/related connections (quan trọng nhất)
ct state established,related accept
ct state invalid drop
# Cho phép ICMP với rate limit
ip protocol icmp limit rate 10/second accept
# Cho phép SSH từ management network
ip saddr 192.168.10.0/24 tcp dport 22 accept
# Cho phép HTTP/HTTPS
tcp dport { 80, 443 } accept
# Cho phép DNS và NTP
udp dport { 53, 123 } accept
tcp dport 53 accept
# Log và drop tất cả còn lại
counter log prefix "FW-DROP: " drop
}
}
# IPv6 table
table ip6 filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
ct state invalid drop
ip6 nexthdr icmpv6 accept
counter log prefix "FW6-DROP: " drop
}
}
EOF
# Kiểm tra syntax trước khi apply
nft -c -f /etc/nftables.conf
# Apply ruleset
nft -f /etc/nftables.conf
# Bật service để tự động load khi reboot
systemctl enable --now nftables
# Xem ruleset đang active
nft list ruleset
Bước 5: Cô lập traffic giữa các nhóm máy
Đây mới là giá trị thật của transparent firewall — kiểm soát traffic giữa các máy trong cùng subnet mà không cần VLAN hay thay đổi gì. Ví dụ: chỉ cho phép app server kết nối vào DB server:
# Tạo named set chứa IP của app servers
nft add set ip filter app_servers { \
type ipv4_addr\; \
elements = { 192.168.10.10, 192.168.10.11, 192.168.10.12 }\; \
}
# Chỉ app_servers mới được kết nối vào DB (192.168.10.50) port 3306
nft add rule ip filter forward \
ip daddr 192.168.10.50 tcp dport 3306 \
ip saddr @app_servers accept
nft add rule ip filter forward \
ip daddr 192.168.10.50 tcp dport 3306 drop
Bước 6: Giám sát và debug
Khi mới triển khai, theo dõi log để đảm bảo không có traffic hợp lệ bị block nhầm. Tuần đầu mình thường để policy accept với log để xem traffic pattern trước khi chuyển sang drop:
# Xem log firewall real-time
journalctl -f | grep "FW-DROP:"
# Xem counter của từng rule (để biết rule nào đang match nhiều)
nft list ruleset | grep counter
# Reset counter để đo traffic trong khoảng thời gian cụ thể
nft reset counters table ip filter
# Test connectivity từ máy trong mạng
ping -c 3 8.8.8.8
curl -I https://google.com
telnet 192.168.10.50 3306
Khi cần tính nhanh subnet để viết rule cho các dải IP khác nhau, mình hay dùng toolcraft.app/vi/tools/developer/ip-subnet-calculator — nhập CIDR là ra ngay network range, broadcast, số host. Rất tiện khi cần phân chia rule cho nhiều segment cùng lúc mà không muốn ngồi tính tay.
Những điểm cần chú ý khi vận hành
- Performance: Bridge firewall xử lý thêm ở software layer. Với đường truyền 1Gbps thông thường thì không đáng kể, nhưng trên 10Gbps+ nên cân nhắc dùng hardware offload hoặc XDP.
- Single point of failure: Transparent firewall là SPOF cho toàn bộ mạng. Trên production nghiêm túc, nên pair với keepalived/VRRP để HA — nếu firewall chết thì mạng không bị đứt hoàn toàn.
- VLAN trunk: Nếu mạng dùng VLAN trunk (802.1Q), cần bật VLAN filtering trên bridge và xử lý từng VLAN riêng. Phức tạp hơn đáng kể so với flat network.
- Logging volume: Rule log cuối chain có thể tạo rất nhiều log nếu có scan/attack. Nên thêm rate limit cho log:
limit rate 5/minute log prefix "FW-DROP: ".
Transparent firewall với nftables là giải pháp mình thấy clean nhất khi cần thêm lớp bảo mật mà không làm phiền đến topology hiện có. Không cần giải thích với khách hàng tại sao phải đổi gateway, không cần maintenance window dài — cắm vào, cấu hình, xong. Và nếu sau này muốn bỏ đi, chỉ cần tháo bridge ra, mạng trở về trạng thái cũ ngay lập tức.

