티스토리 뷰
The definitive guide to nftables — the modern replacement for iptables, ip6tables, arptables, and ebtables. From basic concepts to enterprise-level configurations.
If you’re still using iptables in 2024, you’re missing out on the power and elegance of nftables. This comprehensive guide covers everything you need to master Linux’s modern firewall framework, from fundamental concepts to advanced enterprise configurations.
🚀 Why nftables? The Evolution Story
The Old World: Multiple Tools, Multiple Headaches
# Before nftables - 4 different tools, 4 different syntaxes
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # IPv4
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT # IPv6
arptables -A INPUT --source-ip 1.2.3.4 -j ACCEPT # ARP
ebtables -A INPUT -s 00:11:22:33:44:55 -j ACCEPT # Ethernet
The New World: One Tool, Unified Power
# With nftables - one tool for everything
nft add rule ip filter input tcp dport 22 accept
nft add rule ip6 filter input tcp dport 22 accept
nft add rule arp filter input ip saddr 1.2.3.4 accept
nft add rule bridge filter input ether saddr 00:11:22:33:44:55 accept
Key Advantages of nftables
Feature iptables nftables Performance Linear rule processing O(n) Optimized lookup O(log n) Syntax Complex, inconsistent Clean, unified IPv4/IPv6 Separate tools Single tool Sets/Maps External ipset Built-in Atomicity Rule-by-rule Transaction-based Debugging Limited Advanced tracing
🏗️ nftables Architecture Deep Dive
Core Concepts Hierarchy
nftables Framework
├── Tables (Container for chains)
│ ├── Chains (Container for rules)
│ │ ├── Rules (Filtering logic)
│ │ └── Expressions (Match conditions)
│ ├── Sets (Efficient data storage)
│ └── Maps (Key-value lookups)
└── Address Families (ip, ip6, inet, arp, bridge, netdev)
Address Families Explained
Family Purpose Layer Hooks Available ip IPv4 only Layer 3 input, forward, output, prerouting, postrouting ip6 IPv6 only Layer 3 input, forward, output, prerouting, postrouting inet IPv4 + IPv6 Layer 3 input, forward, output, prerouting, postrouting arp ARP packets Layer 2.5 input, output bridge Ethernet frames Layer 2 input, forward, output, prerouting, postrouting netdev Early packet processing Layer 2 ingress, egress
Hook Points in Network Stack
NETDEV (ingress)
↓
┌─────────────────────────────────────────┐
│ PREROUTING │
│ (routing decisions) │
└─────────────────┬───────────────────────┘
↓
┌───────────────┐
│ ROUTING │
│ DECISION │
└───────┬───────┘
↓
┌─────────────┴─────────────┐
│ │
↓ ↓
┌─────────┐ ┌─────────┐
│ INPUT │ │ FORWARD │
│(local) │ │(route) │
└────┬────┘ └────┬────┘
│ │
↓ ↓
┌─────────┐ ┌─────────┐
│ OUTPUT │ │POSTROUTING│
│(local) │ │ (NAT) │
└────┬────┘ └────┬────┘
│ │
└─────────────┬───────────────┘
↓
┌─────────────┐
│POSTROUTING │
│ (final) │
└─────────────┘
↓
NETDEV (egress)
🔧 Basic nftables Operations
Installation and Setup
# Install nftables (most modern distros include it)
# Debian/Ubuntu
sudo apt update && sudo apt install nftables
# CentOS/RHEL/Fedora
sudo dnf install nftables# Enable and start
sudo systemctl enable nftables
sudo systemctl start nftables# Check version
nft --version
Essential Commands Structure
# Basic command structure
nft [options] command [family] [table] [chain] [rule]
# Examples:
nft list ruleset # List everything
nft add table ip filter # Add table
nft add chain ip filter input # Add chain
nft add rule ip filter input accept # Add rule
Your First nftables Configuration
#!/usr/bin/nft -f
# Clear everything
flush ruleset# Create basic IPv4 firewall
table ip filter {
# Define chains with their properties
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iif lo accept
# Allow established connections
ct state established,related accept
# Allow SSH
tcp dport 22 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
📚 Tables: The Foundation
Creating and Managing Tables
# Create tables for different address families
nft add table ip filter # IPv4 table
nft add table ip6 filter # IPv6 table
nft add table inet filter # Dual-stack table
nft add table arp filter # ARP table
nft add table bridge filter # Bridge table
# List tables
nft list tables# List specific table
nft list table ip filter# Delete table (removes all chains and rules)
nft delete table ip filter# Flush table (removes rules but keeps structure)
nft flush table ip filter
Table Configuration Examples
# Complete table with multiple chains
table ip filter {
# Input chain for incoming packets
chain input {
type filter hook input priority 0; policy drop;
# Rules go here
}
# Forward chain for routed packets
chain forward {
type filter hook forward priority 0; policy drop;
# Rules go here
}
# Output chain for outgoing packets
chain output {
type filter hook output priority 0; policy accept;
# Rules go here
}
# Custom chain (no hook, called from other chains)
chain custom_ssh {
tcp dport 22 limit rate 3/minute accept
log prefix "SSH attempt: " drop
}
}
⛓️ Chains: Traffic Flow Control
Chain Types and Hooks
# Filter chains (most common)
chain input {
type filter hook input priority 0; policy drop;
}
# NAT chains
chain prerouting {
type nat hook prerouting priority -100;
}chain postrouting {
type nat hook postrouting priority 100;
}# Route chains (modify routing decisions)
chain output {
type route hook output priority -150;
}
Chain Priorities (Execution Order)
Priority Typical Use Example -400 Connection tracking ct helper -300 Raw table equivalent notrack -225 SELinux operations selinux -200 Connection tracking ct state -150 Mangle operations mangle -100 DNAT dnat to 0 Filter operations Standard filtering 100 SNAT snat to, masquerade 300 Security operations reject, drop
Advanced Chain Examples
table inet filter {
# Base chain with connection tracking
chain input {
type filter hook input priority 0; policy drop;
# Connection state handling
ct state invalid drop
ct state established,related accept
# Jump to custom chains
tcp dport 22 jump ssh-rules
tcp dport { 80, 443 } jump web-rules
# Final catch-all
log prefix "Dropped: " drop
}
# Custom chain for SSH rules
chain ssh-rules {
# Rate limiting
limit rate 3/minute accept
# Log excessive attempts
log prefix "SSH brute force: "
drop
}
# Custom chain for web traffic
chain web-rules {
# Allow HTTP/HTTPS
accept
}
# Output chain (usually permissive)
chain output {
type filter hook output priority 0; policy accept;
}
}
📏 Rules: The Logic Engine
Rule Syntax Structure
# Basic syntax
nft add rule [family] [table] [chain] [matches] [statements]
# Examples with different components
nft add rule ip filter input tcp dport 22 accept
nft add rule ip filter input ip saddr 192.168.1.0/24 tcp dport 80 counter accept
nft add rule ip filter input ct state established,related counter accept
Match Expressions
# Protocol matching
tcp dport 22 # TCP destination port
udp sport 53 # UDP source port
icmp type echo-request # ICMP type
ip protocol tcp # IP protocol
# Address matching
ip saddr 192.168.1.0/24 # Source IP range
ip daddr != 10.0.0.0/8 # Destination IP (not)
ip saddr { 1.2.3.4, 5.6.7.8 } # Multiple IPs# Interface matching
iif eth0 # Input interface
oif "wlan*" # Output interface (wildcard)
iifname "docker0" # Interface by name# Connection tracking
ct state established # Connection state
ct state new,related # Multiple states
ct direction original # Connection direction# Time-based matching
meta hour "09:00"-"17:00" # Time range
meta day { "Monday", "Friday" } # Specific days# Packet properties
meta length 40-100 # Packet size range
meta mark 0x123 # Packet mark
meta priority 0 # Priority
Statements (Actions)
# Basic actions
accept # Allow packet
drop # Silent drop
reject # Send rejection
return # Return to calling chain
# Logging
log # Basic logging
log prefix "SSH: " # With prefix
log level emerg # Log level# Counters and statistics
counter # Count packets/bytes
counter packets 100 bytes 8000 # Set initial values# Target modification
snat to 1.2.3.4 # Source NAT
dnat to 192.168.1.10 # Destination NAT
masquerade # Dynamic SNAT# Packet modification
meta mark set 0x123 # Set packet mark
meta priority set 0 # Set priority# Rate limiting
limit rate 10/minute # Basic rate limiting
limit rate over 100/minute drop # Burst protection# Advanced actions
queue # Send to userspace
dup to device eth1 # Duplicate packet
🏢 Practical Configuration Examples
1. Basic Home Firewall
#!/usr/bin/nft -f
flush rulesettable inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback
iif lo accept
# Allow established connections
ct state established,related accept
# Allow SSH with rate limiting
tcp dport 22 limit rate 3/minute accept
# Allow web browsing responses
tcp sport { 80, 443 } ct state established accept
# Allow ping
icmp type echo-request limit rate 5/second accept
icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert } accept
# Log and drop everything else
log prefix "Dropped: " drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
2. Web Server Configuration
#!/usr/bin/nft -f
flush rulesettable inet filter {
# Define sets for efficiency
set admin_ips {
type ipv4_addr
elements = { 192.168.1.100, 10.0.0.50 }
}
set web_ports {
type inet_service
elements = { 80, 443, 8080, 8443 }
}
chain input {
type filter hook input priority 0; policy drop;
# Basic allows
iif lo accept
ct state invalid drop
ct state established,related accept
# SSH only from admin IPs
ip saddr @admin_ips tcp dport 22 accept
# Web services
tcp dport @web_ports accept
# ICMP
icmp type echo-request limit rate 5/second accept
icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert } accept
# Rate limiting for web services
tcp dport @web_ports ct state new limit rate 100/second accept
# DDoS protection
tcp flags syn tcp dport @web_ports meter ddos_protection { ip saddr limit rate 10/second } accept
# Log suspicious activity
log prefix "Suspicious: " drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}# NAT table for port redirection
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# Redirect HTTP to HTTPS
tcp dport 80 redirect to :443
}
}
3. Enterprise Network Gateway
#!/usr/bin/nft -f
flush ruleset# Main filter table
table inet filter {
# Network definitions
set internal_nets {
type ipv4_addr
flags interval
elements = { 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12 }
}
set dmz_servers {
type ipv4_addr
elements = { 10.1.0.10, 10.1.0.11, 10.1.0.12 }
}
set blocked_countries {
type ipv4_addr
flags interval
# Would be populated with country IP ranges
}
# Custom chains for organization
chain wan_input {
# WAN interface rules
tcp dport { 80, 443 } dnat to 10.1.0.10
tcp dport 25 dnat to 10.1.0.11
drop
}
chain lan_forward {
# LAN to Internet rules
ip saddr @internal_nets accept
# Block known bad destinations
ip daddr @blocked_countries reject
# Web filtering
tcp dport { 80, 443 } jump web_filter
accept
}
chain web_filter {
# Content filtering logic
# This would integrate with external tools
accept
}
# Main chains
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
# Management access
iifname "eth0" jump wan_input
iifname "eth1" ip saddr @internal_nets accept
# ICMP
icmp type echo-request limit rate 5/second accept
log prefix "INPUT-DROP: " drop
}
chain forward {
type filter hook forward priority 0; policy drop;
ct state established,related accept
# Route based on source
iifname "eth1" jump lan_forward
iifname "eth0" ip daddr @dmz_servers accept
log prefix "FORWARD-DROP: " drop
}
chain output {
type filter hook output priority 0; policy accept;
}
}# NAT table for internet sharing
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# Port forwarding to DMZ
iifname "eth0" tcp dport 80 dnat to 10.1.0.10:80
iifname "eth0" tcp dport 443 dnat to 10.1.0.10:443
iifname "eth0" tcp dport 25 dnat to 10.1.0.11:25
}
chain postrouting {
type nat hook postrouting priority 100;
# Masquerading for internal networks
oifname "eth0" ip saddr @internal_nets masquerade
}
}
🗃️ Sets and Maps: Data Structures
Sets: Efficient IP/Port Collections
# Create different types of sets
table ip filter {
# Simple IP set
set blacklist {
type ipv4_addr
elements = { 192.168.1.100, 192.168.1.101 }
}
# Port set
set web_ports {
type inet_service
elements = { 80, 443, 8080, 8443 }
}
# IP range set with intervals
set private_nets {
type ipv4_addr
flags interval
elements = { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 }
}
# Timeout set (dynamic, auto-expiring)
set rate_limit {
type ipv4_addr
timeout 1h
size 10000
}
# Using sets in rules
chain input {
type filter hook input priority 0; policy drop;
# Block blacklisted IPs
ip saddr @blacklist drop
# Allow web ports
tcp dport @web_ports accept
# Allow internal networks
ip saddr @private_nets accept
}
}
Maps: Key-Value Lookups
table ip nat {
# Port redirection map
map port_redirect {
type inet_service : ipv4_addr . inet_service
elements = {
80 : 192.168.1.10 . 8080,
443 : 192.168.1.10 . 8443,
25 : 192.168.1.11 . 25
}
}
# QoS marking map
map qos_marks {
type ipv4_addr : mark
elements = {
192.168.1.10 : 0x1, # High priority
192.168.1.20 : 0x2, # Medium priority
192.168.1.30 : 0x3 # Low priority
}
}
chain prerouting {
type nat hook prerouting priority -100;
# Use map for port redirection
tcp dport map @port_redirect dnat to
# QoS marking
meta mark set ip saddr map @qos_marks
}
}
Dynamic Set Management
# Add elements to sets at runtime
nft add element ip filter blacklist { 192.168.1.200 }
# Add multiple elements
nft add element ip filter blacklist { 192.168.1.201, 192.168.1.202 }# Delete elements
nft delete element ip filter blacklist { 192.168.1.200 }# List set contents
nft list set ip filter blacklist# Timeout elements (auto-remove after time)
nft add element ip filter rate_limit { 192.168.1.100 timeout 30m }# Flush all elements from set
nft flush set ip filter blacklist
🔄 Connection Tracking Deep Dive
Connection States
# Available connection states
ct state new # First packet of new connection
ct state established # Packets of established connection
ct state related # Related to existing connection (FTP data)
ct state invalid # Invalid packets
ct state untracked # Not tracked
# Practical examples
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Drop invalid packets immediately
ct state invalid counter drop
# Allow established connections
ct state established,related counter accept
# Handle new connections
ct state new tcp dport { 22, 80, 443 } counter accept
# Everything else drops
counter drop
}
}
Connection Tracking Helpers
# FTP helper for data connections
table inet filter {
chain prerouting {
type filter hook prerouting priority -200;
# Enable FTP helper
tcp dport 21 ct helper set "ftp"
}
chain input {
type filter hook input priority 0; policy drop;
# Allow FTP control
tcp dport 21 ct state new accept
# Allow FTP data (marked as related by helper)
ct state related accept
}
}
Advanced Connection Tracking
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Connection direction
ct direction original accept
ct direction reply accept
# Connection mark handling
ct mark 0x123 accept
# Connection labels (for complex state)
ct label "web_conn" accept
# Conntrack zones (namespace separation)
ct zone 1 accept
}
}
🚦 Traffic Shaping and QoS
Rate Limiting
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Basic rate limiting
tcp dport 22 limit rate 3/minute accept
# Burst handling
tcp dport 80 limit rate 100/second burst 200 packets accept
# Per-source rate limiting with meters
tcp dport 80 meter http_rate { ip saddr limit rate 10/second } accept
# Rate limiting with logging
tcp dport 22 limit rate 5/minute accept
tcp dport 22 log prefix "SSH rate limit exceeded: " drop
}
}
Traffic Classification
table inet mangle {
# QoS map for different traffic types
map dscp_map {
type inet_service : dscp
elements = {
22 : cs6, # SSH - high priority
80 : af21, # HTTP - normal
443 : af21, # HTTPS - normal
25 : af11 # SMTP - low priority
}
}
chain postrouting {
type filter hook postrouting priority -150;
# Mark packets based on destination port
ip dscp set tcp dport map @dscp_map
# Alternative: mark based on source
ip saddr 192.168.1.10 meta priority set 1
ip saddr 192.168.1.20 meta priority set 2
}
}
🔍 Logging and Monitoring
Comprehensive Logging Setup
table inet filter {
# Logging chain
chain log_and_drop {
limit rate 5/minute log prefix "DROPPED: " level warn
counter drop
}
chain log_and_accept {
log prefix "ACCEPTED: " level info
counter accept
}
chain input {
type filter hook input priority 0; policy drop;
# Allow known good traffic
ct state established,related counter accept
iif lo accept
# Log SSH attempts
tcp dport 22 log prefix "SSH attempt from: " accept
# Log web traffic (sample only)
tcp dport { 80, 443 } limit rate 1/minute log prefix "WEB: "
tcp dport { 80, 443 } accept
# Log everything else before dropping
jump log_and_drop
}
}
Advanced Logging with JSON
# Configure structured logging
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# JSON-formatted logs
tcp dport 22 log prefix '{"event":"ssh_attempt","src":"' \
log suffix '","dst":"local","action":"accept"}' accept
# Rate-limited verbose logging
limit rate 1/minute log prefix "DETAILED: " \
flags all level debug accept
}
}
Monitoring Script Integration
#!/bin/bash
# nftables monitoring script
# Real-time rule statistics
watch_rules() {
watch -n 2 'nft list ruleset | grep counter'
}# Connection tracking statistics
watch_conntrack() {
watch -n 1 '
echo "=== Connection Tracking Stats ==="
echo "Active: $(cat /proc/net/nf_conntrack | wc -l)"
echo "Max: $(cat /proc/sys/net/netfilter/nf_conntrack_max)"
echo
echo "=== Top Connections ==="
cat /proc/net/nf_conntrack | awk "{print \$1, \$3}" | sort | uniq -c | sort -nr | head -10
'
}# Log analysis
analyze_logs() {
echo "=== nftables Log Analysis ==="
# SSH attempts
echo "SSH attempts in last hour:"
grep "$(date --date='1 hour ago' '+%b %d %H')" /var/log/messages | \
grep "SSH attempt" | wc -l
# Dropped packets by source
echo -e "\nTop dropped sources:"
grep "DROPPED:" /var/log/messages | \
awk '{print $NF}' | sort | uniq -c | sort -nr | head -10
}case "$1" in
rules) watch_rules ;;
conntrack) watch_conntrack ;;
logs) analyze_logs ;;
*) echo "Usage: $0 {rules|conntrack|logs}" ;;
esac
🔒 Security-Focused Configurations
DDoS Protection
table inet filter {
# Rate limiting sets
set syn_flood_limit {
type ipv4_addr
timeout 1m
size 10000
}
set ddos_protection {
type ipv4_addr
timeout 10m
size 10000
}
chain input {
type filter hook input priority 0; policy drop;
# Basic flood protection
tcp flags syn meter syn_rate { ip saddr limit rate 10/second } accept
tcp flags syn add @syn_flood_limit { ip saddr timeout 1m } drop
# Connection limit per IP
tcp dport { 80, 443 } meter connections { ip saddr ct count over 20 } drop
# Packet size anomaly detection
meta length > 1000 tcp flags syn drop
# Fragment attack protection
ip protocol tcp ip fragoff & 0x1fff != 0 drop
# Bogus TCP flags
tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg drop
tcp flags & (fin|syn|rst|psh|ack|urg) == 0 drop
# XMAS and NULL scans
tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|ack|urg drop
tcp flags & (fin|syn|rst|psh|ack|urg) == syn|rst drop
}
}
Intrusion Detection Integration
table inet filter {
# Suspicious activity detection
set port_scanners {
type ipv4_addr
timeout 1h
size 10000
}
set brute_force_ips {
type ipv4_addr
timeout 24h
size 10000
}
chain input {
type filter hook input priority 0; policy drop;
# Block known bad actors
ip saddr @port_scanners drop
ip saddr @brute_force_ips drop
# Detect port scanning
tcp flags syn meter port_scan { ip saddr and 255.255.255.0 limit rate 5/second burst 10 packets } accept
tcp flags syn add @port_scanners { ip saddr }
tcp flags syn log prefix "Port scan detected: " drop
# SSH brute force detection
tcp dport 22 ct state new meter ssh_attempts { ip saddr limit rate 3/minute } accept
tcp dport 22 ct state new add @brute_force_ips { ip saddr }
tcp dport 22 ct state new log prefix "SSH brute force: " drop
# Legitimate traffic
ct state established,related accept
tcp dport { 80, 443 } accept
}
}
Geo-blocking Implementation
#!/usr/bin/nft -f
# This would typically load country IP ranges from external files
define CHINA_IPS = { 1.2.4.0/22, 1.2.8.0/21 } # Simplified example
define RUSSIA_IPS = { 5.8.8.0/21, 5.8.16.0/20 } # Simplified exampletable inet filter {
set blocked_countries {
type ipv4_addr
flags interval
elements = { $CHINA_IPS, $RUSSIA_IPS }
}
set allowed_countries {
type ipv4_addr
flags interval
# Would contain allowed country ranges
}
chain input {
type filter hook input priority 0; policy drop;
# Allow internal networks
ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } accept
# Block specific countries
ip saddr @blocked_countries log prefix "Geo-blocked: " drop
# Only allow from specific countries (if whitelist mode)
# ip saddr @
20
2
'Study > System' 카테고리의 다른 글
| [윈도우] CPL(제어판) & MMC(관리도구) 모듈 (0) | 2025.08.22 |
|---|---|
| [Regex] Regular Expressions Cheat Sheet (1) | 2025.04.15 |
| Ubuntu 18 NIC 설정 (1) | 2023.12.05 |
| php 여러 버전 설치 on Ubuntu22.04 (0) | 2023.09.13 |
| [ELK Stack] Elastic, Kibana 설치 (0) | 2023.09.11 |
- Total
- Today
- Yesterday
- metasploitable3
- ssl decrypt
- filesystem check
- dvwa_command
- editcap
- capinfos
- MySQL csv
- pcapng
- docker_dvwa
- ${1##*.}
- bash modification
- mergecap
- bash parameter
- tcpdstat
- dvwa
- docker
- 리눅스 버전
- history timestamp
- dvwa_bruteforce
- excel_aton
- megacli
- oracle 11gr2
- 도커
- webhack
- 윈도우 패스워드 복구
- text2pcap
- NX ASLR
- cisco ssh
- recovery file on linux
- tshark
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
