sudo apt-get update && sudo apt-get install -y nftables
sudo systemctl enable --now nftables
sudo nft -f /etc/nftables.conf
sudo nft list ruleset # check
# 1. Check and manage rules
# Show all rules
sudo nft list ruleset
# Save rules to a file
sudo nft list ruleset > /etc/nftables.conf
# Load rules from a file
sudo nft -f /etc/nftables.conf
# 2. Working with tables
# Create a table
sudo nft add table inet filter
# Delete a table
sudo nft delete table inet filter
# 3. Working with chains
# Create a chain for incoming traffic
sudo nft add chain inet filter input { type filter hook input priority 0; }
# Delete a chain
sudo nft delete chain inet filter input
#4. Adding rules
# Allow SSH (port 22)
sudo nft add rule inet filter input tcp dport 22 accept
# Allow HTTP and HTTPS
sudo nft add rule inet filter input tcp dport { 80, 443 } accept
# Allow ICMP (ping)
sudo nft add rule inet filter input icmp type echo-request accept
# Allow traffic from a specific IP
sudo nft add rule inet filter input ip saddr 192.168.1.100 accept
# Deny everything else
sudo nft add rule inet filter input drop
# 5. Managing rules
# Delete a specific rule (by handle)
# First, list the rules:
sudo nft list chain inet filter input
# Then delete, e.g., rule with handle 2:
sudo nft delete rule inet filter input handle 2
# 6. System integration
# Enable rules at boot
# Main config file: /etc/nftables.conf
# Enable service:
sudo systemctl enable nftables
sudo systemctl start nftables
# Concepts:
table = a ruleset (e.g., filter, nat).
chain = a hook for traffic (input, forward, output).
rule = the actual filtering rule (accept, drop, etc.).
# iptables (SSH, HTTP, HTTPS)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#nftables (SSH, HTTP, HTTPS)
tcp dport {22, 80, 443} accept
# iptables (Block a single IP address)
iptables -A INPUT -s 192.168.1.10 -j DROP
iptables -A INPUT -s 192.168.1.20 -j DROP
iptables -A INPUT -s 192.168.1.30 -j DROP
# nftables (Block a single IP address)
ip saddr {192.168.1.10, 192.168.1.20, 192.168.1.30} drop
# iptables Full ruleset (DROP, loopback, established, ssh, http, https)
iptables -P INPUT DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
# nftables Full ruleset (DROP, loopback, established, ssh, http, https)
chain input {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
tcp dport {22,80,443} accept
icmp type echo-request accept
}
# Quick Reference with Examples
# 1. Basic structure
# iptables: separate commands for filter, nat, mangle, etc.
# nftables: one unified syntax, everything managed with nft.
# 2. Allow SSH (port 22)
# iptables
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# nftables
sudo nft add rule inet filter input tcp dport 22 accept
# 3. Allow HTTP/HTTPS (ports 80, 443)
# iptables
sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# nftables
sudo nft add rule inet filter input tcp dport {80, 443} accept
# 4. Allow ICMP (ping)
# iptables
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# nftables
sudo nft add rule inet filter input icmp type echo-request accept
# 5. Allow traffic from a specific IP
# iptables
sudo iptables -A INPUT -s 192.168.1.100 -j ACCEPT
# nftables
sudo nft add rule inet filter input ip saddr 192.168.1.100 accept
# 6. Drop all other traffic
# iptables
sudo iptables -A INPUT -j DROP
# nftables
sudo nft add rule inet filter input drop
# 7. Logging packets
#iptables
# Log and drop invalid packets
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j LOG --log-prefix "INVALID: "
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
# nftables
sudo nft add rule inet filter input ct state invalid log prefix "INVALID: " drop
# 8. NAT (port forwarding)
# iptables
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.50:80
# nftables
sudo nft add table ip nat
sudo nft add chain ip nat prerouting { type nat hook prerouting priority 0; }
sudo nft add rule ip nat prerouting tcp dport 8080 dnat to 192.168.1.50:80
# 9. Save & restore rules
# iptables
sudo iptables-save > /etc/iptables/rules.v4
sudo iptables-restore < /etc/iptables/rules.v4
# nftables
sudo nft list ruleset > /etc/nftables.conf
sudo nft -f /etc/nftables.conf
# Summary
# iptables = old but still works, rule-by-rule.
# nftables = modern replacement, shorter syntax, one tool for everything.
Both support logging, but nftables logging is cleaner and more flexible.
# Example (Full version)
#!/usr/sbin/nft -f
flush ruleset
# =========================
# nftables: base template
# =========================
# Таблицы:
# - inet filter : general filtration for IPv4/IPv6
# - ip nat : NAT for IPv4 (SNAT/MASQ, DNAT)
# ---------- FILTER ----------
table inet filter {
# Sets
set allowed_tcp_ports = { # Allowed services
type inet_service; # 0..65535
elements = { 22, 80, 443 } # SSH, HTTP, HTTPS
(add more if needed)
}
# Example: SSH access from selected subs and IP only
# set admin_src = { type ipv4_addr; flags interval; elements = { 192.0.2.0/24, 203.0.113.10 } }
chain input {
type filter hook input priority 0; policy drop;
# Base level trust
iif "lo" accept
ct state established,related accept
# ICMP/ICMPv6: ICMP and important messages, with rate-limit
ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded } limit rate 20/second accept
ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply, destination-unreachable, time-exceeded, packet-too-big } limit rate 20/second accept
# DHCPv6 for a client (if the server gets IP v6 address)
udp dport 546 udp sport 547 accept
# SSH / HTTP / HTTPS (see Sets above)
tcp dport @allowed_tcp_ports accept
# Example: SSH access — only for admin_src (see above and uncomment if needed)
# tcp dport 22 ip saddr @admin_src accept
# Logs
limit rate 10/second counter log prefix "NFT DROP: " group 0 drop
}
chain forward {
type filter hook forward priority 0; policy drop;
# Allow from LAN to WAN
# See your interfaces and use them instead "lan0" и "wan0"
iif "lan0" oif "wan0" accept
ct state established,related accept
# Log and Drop
limit rate 10/second counter log prefix "NFT FWD DROP: " group 0 drop
}
chain output {
type filter hook output priority 0; policy accept;
# Usually all outgoes traffic is allowed. If no - add rules
}
}
# ---------- NAT (IPv4) ----------
table ip nat {
chain prerouting {
type nat hook prerouting priority -100;
# Example DNAT (port-forvarding)
# WAN: tcp/2222 --> LAN: 192.168.10.50:22
# iif "wan0" tcp dport 2222 dnat to 192.168.10.50:22
}
chain postrouting {
type nat hook postrouting priority 100;
# Masquerade to go out (dynamic SNAT)
# Change the "wan0" to your interface
oif "wan0" masquerade
}
}
sudo apt install nftables netfilter-persistent
sudo systemctl enable --now nftables netfilter-persistent