
Nftables คืออะไร? ทำไมต้องมาแทน iptables?
Nftables (อ่านว่า เอ็น-เอฟ-เทเบิลส์) คือ Framework สำหรับ Packet Filtering และ Classification ใน Linux Kernel ที่ถูกพัฒนาขึ้นมาเพื่อทดแทน iptables, ip6tables, arptables และ ebtables ซึ่งเป็นเครื่องมือ Firewall แบบเดิมที่ใช้กันมานานกว่า 20 ปี Nftables ถูก Merge เข้า Linux Kernel ตั้งแต่เวอร์ชัน 3.13 (ปี 2014) และตั้งแต่ปี 2026 Linux Distributions หลักทุกตัว (Debian 12+, Ubuntu 22.04+, RHEL 9+, Fedora 33+) ล้วนใช้ Nftables เป็น Default Firewall Framework แล้ว
ปัญหาหลักของ iptables คือ Code Duplication (iptables, ip6tables, arptables, ebtables ใช้ Code base แยกกัน), Performance ที่ลดลงเมื่อมี Rules จำนวนมาก (Linear matching), Syntax ที่ซับซ้อนและเรียนรู้ยาก, ไม่รองรับ Atomic Rule Replacement (ต้อง Flush แล้ว Reload ทั้งหมด) และไม่มี Sets/Maps ต้องสร้าง Rules ซ้ำ ๆ สำหรับแต่ละ IP/Port Nftables แก้ปัญหาเหล่านี้ทั้งหมดด้วย Architecture ที่ออกแบบใหม่ตั้งแต่ต้น
Nftables vs iptables — เปรียบเทียบแบบชัดเจน
| คุณสมบัติ | iptables | nftables |
|---|---|---|
| IPv4/IPv6 | แยกคำสั่ง (iptables / ip6tables) | คำสั่งเดียว (nft) รองรับทั้ง IPv4, IPv6 |
| Performance | Linear matching (O(n)) | ใช้ Sets/Maps (O(1) lookup) |
| Atomic Updates | ไม่รองรับ (ต้อง flush + reload) | รองรับ (atomic rule replacement) |
| Syntax | ซับซ้อน หลายคำสั่ง (-A, -I, -D, -j) | เรียบง่าย อ่านเข้าใจง่ายกว่า |
| Sets | ต้องใช้ ipset แยก | มี Sets/Maps ในตัว |
| Rule Format | คำสั่ง CLI ทีละบรรทัด | ไฟล์ Script ที่จัดโครงสร้างได้ |
| Tables/Chains | Fixed tables (filter, nat, mangle, raw) | สร้างเองได้ ตั้งชื่อเองได้ |
| Kernel Module | x_tables (legacy) | nf_tables (modern) |
| Tracing/Debug | ใช้ LOG target + dmesg | nft monitor trace (real-time) |
nft Command — Syntax พื้นฐาน
โครงสร้าง nftables: Tables → Chains → Rules
nftables ใช้โครงสร้าง 3 ระดับ ได้แก่ Tables (กลุ่มของ Chains ระบุ Family เช่น inet, ip, ip6, bridge), Chains (กลุ่มของ Rules ระบุ Type และ Hook point), และ Rules (เงื่อนไข match + action)
# ดู Rules ทั้งหมด
nft list ruleset
# สร้าง Table (inet = IPv4 + IPv6)
nft add table inet my_firewall
# สร้าง Chain (input = incoming traffic)
nft add chain inet my_firewall input {
type filter hook input priority 0; policy drop;
}
# สร้าง Chain สำหรับ output
nft add chain inet my_firewall output {
type filter hook output priority 0; policy accept;
}
# สร้าง Chain สำหรับ forward
nft add chain inet my_firewall forward {
type filter hook forward priority 0; policy drop;
}
# ดู Chains ใน Table
nft list table inet my_firewall
Rules — Match + Action
# อนุญาต Loopback
nft add rule inet my_firewall input iif lo accept
# อนุญาต Established/Related connections
nft add rule inet my_firewall input ct state established,related accept
# อนุญาต SSH (port 22)
nft add rule inet my_firewall input tcp dport 22 accept
# อนุญาต HTTP/HTTPS
nft add rule inet my_firewall input tcp dport { 80, 443 } accept
# อนุญาต ICMP (ping)
nft add rule inet my_firewall input ip protocol icmp accept
nft add rule inet my_firewall input ip6 nexthdr icmpv6 accept
# อนุญาต DNS (สำหรับ DNS Server)
nft add rule inet my_firewall input udp dport 53 accept
nft add rule inet my_firewall input tcp dport 53 accept
# Block IP เฉพาะ
nft add rule inet my_firewall input ip saddr 192.168.1.100 drop
# Log + Drop traffic ที่ไม่ตรงกับ Rules ใด (ก่อน default drop)
nft add rule inet my_firewall input log prefix "DROPPED: " drop
# แทรก Rule ที่ตำแหน่งเฉพาะ (position)
nft insert rule inet my_firewall input position 3 tcp dport 8080 accept
# ลบ Rule (ต้องรู้ handle number)
nft -a list table inet my_firewall # ดู handle
nft delete rule inet my_firewall input handle 7
Sets และ Maps — พลังที่ iptables ไม่มี
Named Sets
Sets เป็นฟีเจอร์ที่ทรงพลังที่สุดของ nftables ช่วยให้คุณจัดกลุ่ม IP addresses, ports หรือค่าอื่น ๆ เข้าด้วยกัน แล้วอ้างอิงใน Rules ได้ Performance ดีกว่า Rules ซ้ำ ๆ มากเพราะใช้ Hash lookup (O(1)) แทน Linear matching (O(n))
# สร้าง Named Set สำหรับ IP ที่อนุญาต SSH
nft add set inet my_firewall ssh_allowed {
type ipv4_addr;
comment "IPs allowed to SSH";
}
# เพิ่ม IP เข้า Set
nft add element inet my_firewall ssh_allowed { 10.0.0.0/24, 192.168.1.0/24 }
# ใช้ Set ใน Rule
nft add rule inet my_firewall input ip saddr @ssh_allowed tcp dport 22 accept
# Set แบบ Interval (IP ranges)
nft add set inet my_firewall blocked_ranges {
type ipv4_addr;
flags interval;
}
nft add element inet my_firewall blocked_ranges { 10.10.0.0/16, 172.16.0.0/12 }
# Set แบบ Timeout (auto-expire)
nft add set inet my_firewall rate_limited {
type ipv4_addr;
timeout 1h;
comment "Rate limited IPs - auto expire after 1 hour";
}
nft add element inet my_firewall rate_limited { 203.0.113.50 timeout 30m }
# Set สำหรับ Ports
nft add set inet my_firewall web_ports {
type inet_service;
elements = { 80, 443, 8080, 8443 };
}
nft add rule inet my_firewall input tcp dport @web_ports accept
Maps — Verdict Maps
# Verdict Map — กำหนด action ตาม port
nft add map inet my_firewall port_policy {
type inet_service : verdict;
}
nft add element inet my_firewall port_policy {
22 : accept,
80 : accept,
443 : accept,
8080 : drop,
3306 : drop
}
nft add rule inet my_firewall input tcp dport vmap @port_policy
# Map IP → Interface (สำหรับ Routing/NAT)
nft add map inet my_firewall ip_to_mark {
type ipv4_addr : mark;
}
nft add element inet my_firewall ip_to_mark {
10.0.1.0/24 : 0x1,
10.0.2.0/24 : 0x2,
10.0.3.0/24 : 0x3
}
# Concatenation — match หลาย fields พร้อมกัน
nft add set inet my_firewall allowed_services {
type ipv4_addr . inet_service;
}
nft add element inet my_firewall allowed_services {
10.0.1.0/24 . 22,
10.0.2.0/24 . 80,
10.0.2.0/24 . 443
}
nft add rule inet my_firewall input ip saddr . tcp dport @allowed_services accept
NAT ด้วย nftables
# สร้าง NAT Table
nft add table ip nat_table
nft add chain ip nat_table prerouting {
type nat hook prerouting priority -100;
}
nft add chain ip nat_table postrouting {
type nat hook postrouting priority 100;
}
# Source NAT (Masquerade) — สำหรับ Internet sharing
nft add rule ip nat_table postrouting oif eth0 masquerade
# SNAT — กำหนด Source IP
nft add rule ip nat_table postrouting oif eth0 snat to 203.0.113.1
# Destination NAT (Port Forward)
# Forward port 80 → internal server 10.0.1.10:8080
nft add rule ip nat_table prerouting iif eth0 tcp dport 80 dnat to 10.0.1.10:8080
# Port Forward + Forward chain
nft add rule inet my_firewall forward ip daddr 10.0.1.10 tcp dport 8080 accept
# Full NAT example สำหรับ Router
#!/usr/sbin/nft -f
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
# Port forward: 80 → web server
iif eth0 tcp dport 80 dnat to 10.0.1.10:80
# Port forward: 443 → web server
iif eth0 tcp dport 443 dnat to 10.0.1.10:443
# Port forward: 2222 → SSH on server 2
iif eth0 tcp dport 2222 dnat to 10.0.1.20:22
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# Masquerade traffic going out eth0
oif eth0 masquerade
}
}
Migration จาก iptables
iptables-translate — เครื่องมือช่วยแปลง
Linux มีเครื่องมือ iptables-translate ที่ช่วยแปลง iptables rules เป็น nftables syntax โดยอัตโนมัติ เหมาะสำหรับการ Migrate Rules จำนวนมาก
# แปลง iptables rule เดี่ยว
iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# ผลลัพธ์: nft add rule ip filter INPUT tcp dport 22 counter accept
iptables-translate -A INPUT -s 192.168.1.0/24 -p tcp -m multiport --dports 80,443 -j ACCEPT
# ผลลัพธ์: nft add rule ip filter INPUT ip saddr 192.168.1.0/24 tcp dport { 80, 443 } counter accept
# แปลง Ruleset ทั้งหมด
iptables-save | iptables-restore-translate > nftables_migrated.nft
# ตรวจสอบ Ruleset ที่แปลงแล้ว
nft -c -f nftables_migrated.nft
# ถ้าโอเค ก็ Load
nft -f nftables_migrated.nft
# ขั้นตอน Migration ที่แนะนำ:
# 1. Export iptables rules ปัจจุบัน (iptables-save > backup.rules)
# 2. แปลงเป็น nftables (iptables-restore-translate)
# 3. ตรวจสอบและแก้ไข Rules ที่แปลงไม่สมบูรณ์
# 4. ทดสอบบน Test environment
# 5. Load nftables rules
# 6. ตรวจสอบ connectivity ทั้งหมด
# 7. Disable iptables service
# 8. Enable nftables service
nftables + firewalld
firewalld เป็น Firewall Management daemon ที่ใช้ใน RHEL/CentOS/Fedora ตั้งแต่เวอร์ชัน v0.9.0 firewalld ใช้ nftables เป็น Backend แทน iptables คุณสามารถใช้ firewalld CLI (firewall-cmd) ต่อไปได้ตามปกติ แต่ Backend จะสร้าง nftables rules แทน
# ตรวจสอบ Backend ของ firewalld
firewall-cmd --version
cat /etc/firewalld/firewalld.conf | grep FirewallBackend
# FirewallBackend=nftables
# ใช้ firewalld ตามปกติ — มันจะสร้าง nftables rules ให้
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
# ดู nftables rules ที่ firewalld สร้าง
nft list ruleset | head -50
# สำหรับ Custom rules ที่ firewalld ไม่รองรับ
# สามารถเขียน nftables rules เพิ่มเติมใน
# /etc/nftables/custom.nft แล้ว include ใน firewalld
nftables สำหรับ Docker
Docker ใช้ iptables เป็น Default สำหรับจัดการ Network ตั้งแต่ Docker 20.10+ สามารถตั้งค่าให้ใช้ nftables ได้ แต่ต้องระวังเรื่อง Compatibility เพราะ Docker จะสร้าง Rules ของตัวเองเพื่อจัดการ Container networking
# /etc/docker/daemon.json
{
"iptables": true,
"ip6tables": true
}
# Docker ยังใช้ iptables compatibility layer
# (iptables-nft) ซึ่งแปลง iptables commands เป็น nftables rules
# ตรวจสอบว่า iptables ใช้ nft backend
iptables --version
# iptables v1.8.9 (nf_tables)
# สำหรับ Custom firewall rules กับ Docker
# สร้าง Chain แยกเพื่อไม่ให้ชนกับ Docker rules
nft add table inet docker_custom
nft add chain inet docker_custom input {
type filter hook input priority -1; policy accept;
}
# priority -1 ทำให้ Rules นี้ทำงานก่อน Docker rules
# Block port ที่ Docker expose
# ต้องทำที่ PREROUTING (ไม่ใช่ INPUT) เพราะ Docker ใช้ DNAT
nft add table ip raw_filter
nft add chain ip raw_filter prerouting {
type filter hook prerouting priority -300; policy accept;
}
nft add rule ip raw_filter prerouting tcp dport 3306 ip saddr != 10.0.0.0/8 drop
Stateful Firewall — Connection Tracking
nftables มี Connection Tracking (conntrack) ในตัว ซึ่งเป็นพื้นฐานของ Stateful Firewall ทำให้สามารถ track connection state (new, established, related, invalid) ได้
#!/usr/sbin/nft -f
# Complete Stateful Firewall Configuration
flush ruleset
table inet firewall {
# Sets
set ssh_allowed {
type ipv4_addr
elements = { 10.0.0.0/8, 192.168.0.0/16 }
}
set blocked_ips {
type ipv4_addr
flags timeout
comment "Dynamic blacklist with auto-expiry"
}
# Input Chain
chain input {
type filter hook input priority 0; policy drop;
# Connection tracking
ct state invalid drop
ct state established,related accept
# Loopback
iif lo accept
# Drop blocked IPs
ip saddr @blocked_ips drop
# ICMP (rate limited)
ip protocol icmp limit rate 10/second accept
ip6 nexthdr icmpv6 limit rate 10/second accept
# SSH (from allowed IPs only)
ip saddr @ssh_allowed tcp dport 22 accept
# Web services
tcp dport { 80, 443 } accept
# DNS (if DNS server)
# udp dport 53 accept
# tcp dport 53 accept
# Monitoring (Zabbix Agent)
tcp dport 10050 accept
# Log dropped packets (rate limited)
limit rate 5/minute log prefix "NFT-DROP: " drop
}
# Output Chain
chain output {
type filter hook output priority 0; policy accept;
}
# Forward Chain
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
ct state invalid drop
}
}
Rate Limiting — ป้องกัน DDoS
# Rate limit SSH connections (ป้องกัน brute-force)
nft add rule inet firewall input tcp dport 22 ct state new limit rate 3/minute burst 5 packets accept
# Rate limit HTTP connections per source IP
nft add rule inet firewall input tcp dport 80 ct state new meter http_meter { ip saddr limit rate 30/second burst 50 packets } accept
# Rate limit ICMP (ป้องกัน ping flood)
nft add rule inet firewall input ip protocol icmp limit rate 5/second burst 10 packets accept
# SYN flood protection
nft add rule inet firewall input tcp flags syn limit rate 100/second burst 150 packets accept
# Dynamic blacklist — block IP ที่ส่ง traffic มากเกินไป
nft add rule inet firewall input meter flood_meter { ip saddr limit rate over 100/second } add @blocked_ips { ip saddr timeout 10m } drop
Logging และ Tracing
# Log ด้วย prefix
nft add rule inet firewall input tcp dport 22 log prefix "SSH-ACCESS: " accept
# Log with nflog (ส่งไปยัง ulogd2 สำหรับเก็บใน Database)
nft add rule inet firewall input log group 1 prefix "ALL-INPUT: "
# ตั้ง ulogd2 สำหรับเก็บ log
# /etc/ulogd.conf
# [log1]
# group=1
# [output]
# plugin="ulogd_output_PGSQL.so"
# Real-time tracing (debug)
nft monitor trace
# เปิด trace สำหรับ traffic เฉพาะ
nft add rule inet firewall input meta nftrace set 1
# ดู connection tracking
conntrack -L
conntrack -E # real-time events
# ดูสถิติ Rules (counter)
nft add rule inet firewall input tcp dport 80 counter accept
nft list chain inet firewall input # จะเห็น packets/bytes count
nftables Scripting — ไฟล์ Configuration
# /etc/nftables.conf — Main configuration file
#!/usr/sbin/nft -f
# Flush existing rules
flush ruleset
# Include additional configs
include "/etc/nftables.d/*.nft"
# Variables
define WAN_IF = eth0
define LAN_IF = eth1
define LAN_NET = 10.0.0.0/24
define DNS_SERVERS = { 8.8.8.8, 8.8.4.4 }
define ADMIN_IPS = { 10.0.0.10, 10.0.0.20 }
table inet filter {
set web_ports {
type inet_service
elements = { 80, 443 }
}
chain input {
type filter hook input priority 0; policy drop;
ct state invalid drop
ct state established,related accept
iif lo accept
# Admin access
ip saddr $ADMIN_IPS tcp dport 22 accept
# Web
iif $WAN_IF tcp dport @web_ports accept
# LAN full access
iif $LAN_IF ip saddr $LAN_NET accept
}
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
# LAN to WAN
iif $LAN_IF oif $WAN_IF accept
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100;
oif $WAN_IF masquerade
}
}
# เปิดใช้ nftables service
# systemctl enable nftables
# systemctl start nftables
# ทดสอบ config ก่อน load
# nft -c -f /etc/nftables.conf
# Load config
# nft -f /etc/nftables.conf
Best Practices สำหรับ nftables
1. ใช้ Atomic Rule Loading
เขียน Rules ทั้งหมดในไฟล์ .nft แล้ว load ทีเดียว (nft -f file.nft) แทนการรัน nft add rule ทีละคำสั่ง เพราะ Atomic loading ทำให้ไม่มีช่วงที่ Firewall ไม่มี Rules (race condition)
2. ใช้ Sets แทน Rules ซ้ำ ๆ
แทนที่จะสร้าง Rule แยกสำหรับทุก IP ให้ใช้ Named Sets ซึ่ง Performance ดีกว่ามาก (O(1) vs O(n)) และจัดการง่ายกว่า
3. ตั้ง Default Drop Policy
Input chain ควรตั้ง default policy เป็น drop เสมอ แล้ว whitelist traffic ที่อนุญาต อย่าใช้ default accept แล้ว blacklist เพราะจะพลาดง่าย
4. ใช้ Connection Tracking
ตั้ง ct state established,related accept ไว้ต้น chain เสมอ เพื่อให้ return traffic ผ่านได้โดยไม่ต้องมี explicit rules
5. Rate Limit อย่างเหมาะสม
ใช้ Rate limiting สำหรับ SSH, ICMP และ Services สำคัญ เพื่อป้องกัน Brute-force และ DDoS แต่อย่าตั้งเข้มเกินไปจน Block traffic ปกติ
6. แยกไฟล์ Config
ใช้ include directive แยก Rules ตามหมวดหมู่ เช่น base.nft (พื้นฐาน), web.nft (Web services), nat.nft (NAT rules), blacklist.nft (Blocked IPs) เพื่อให้จัดการง่าย
7. Backup ก่อนเปลี่ยน
ก่อนแก้ไข Rules เสมอให้ backup ก่อนด้วย nft list ruleset > backup_$(date +%Y%m%d).nft ถ้าพลาดสามารถ restore ได้ทันที
8. ทดสอบใน Test Environment
ทดสอบ Rules ใน VM หรือ Container ก่อนเสมอ ใช้ nft -c -f file.nft เพื่อ Check syntax โดยไม่ load จริง ถ้า Remote server ให้ใช้ at command ตั้ง flush ruleset ไว้เผื่อ lock ตัวเอง
สรุป
Nftables เป็น Linux Firewall Framework ยุคใหม่ที่ทดแทน iptables ได้อย่างสมบูรณ์ ด้วย Syntax ที่เรียบง่ายกว่า Performance ที่ดีกว่าด้วย Sets/Maps การรองรับ IPv4/IPv6 ในคำสั่งเดียว Atomic rule updates และ Built-in connection tracking ทำให้เป็นทางเลือกที่ดีกว่าสำหรับ SysAdmin ในปี 2026
สำหรับผู้ที่ยังใช้ iptables อยู่ แนะนำให้เริ่มเรียนรู้ nftables syntax ใช้ iptables-translate ช่วยแปลง Rules เดิม ทดสอบใน Test environment แล้วค่อย ๆ Migrate ไป เพราะ iptables จะค่อย ๆ ถูก Deprecate ในอนาคต และ Linux distributions ใหม่ ๆ จะใช้ nftables เป็น Default ทั้งหมด การเรียนรู้ nftables วันนี้คือการลงทุนที่คุ้มค่าสำหรับ SysAdmin ทุกคน