nftables is the modern Linux firewall framework that replaces iptables. It offers a single unified interface for IPv4, IPv6, ARP, and bridge filtering, with better performance and a cleaner syntax. This tutorial walks through designing a production-grade nftables ruleset for a VPS running web applications, including rate limiting, port knocking alternatives, and logging.
Why nftables Over iptables?
nftables offers several advantages that matter on a resource-constrained VPS:
- Single kernel footprint — One nftables kernel module replaces iptables, ip6tables, arptables, and ebtables, saving memory.
- Atomic rule replacement — The entire ruleset is loaded atomically. A syntax error does not leave you with a broken firewall.
- Sets and maps — Native support for IP sets and dictionaries eliminates the need for
ipsetas a separate tool. - Performance — nftables uses a B-tree for rule lookup, which scales better than iptables’ linear chain traversal.
Basic nftables Installation
# Install nftables on Ubuntu/Debian
sudo apt install nftables -y
# Enable and start the service
sudo systemctl enable nftables
sudo systemctl start nftables
# Verify the installation
sudo nft list ruleset
Designing a Production Ruleset
A production web server ruleset should follow these principles: default-deny inbound, allow established connections, permit only necessary services, and log dropped packets for debugging.
#!/usr/sbin/nft -f
# /etc/nftables.conf — Production web server ruleset
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Allow loopback traffic
iif lo accept
# Allow established and related connections
ct state established,related accept
# Allow SSH (port 22) — restrict to your IP if possible
tcp dport 22 accept
# Allow HTTP and HTTPS
tcp dport {80, 443} accept
# Allow ICMP for diagnostics (limit to avoid abuse)
ip protocol icmp icmp type {echo-request, echo-reply} limit rate 10/second accept
# Allow outgoing ICMP from the server
ip protocol icmp icmp type {destination-unreachable, time-exceeded} accept
# Log and drop everything else
log prefix "nftables-drop: " flags all limit rate 5/second
counter drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Rate Limiting SSH Connections
Brute-force SSH attacks are constant on any public VPS. Instead of installing Fail2ban, you can handle rate limiting directly in nftables:
# Add a rate limit to the SSH rule in the input chain
tcp dport 22 ct state new limit rate 5/minute accept
log prefix "ssh-rate-limit: " tcp dport 22 ct state new counter drop
# Complete SSH protection with dynamic set for ban
# Add this before the SSH accept rule:
tcp dport 22 ct state new \
add @ssh_bruteforce { ip saddr limit rate 5/minute } \
accept
# Define the set at the top of your table
set ssh_bruteforce {
type ipv4_addr
size 1024
timeout 10m
}
Using nftables Sets for Dynamic Allow/Deny Lists
Sets make it easy to maintain allowlists and blocklists without editing the ruleset file:
# Define a set for allowed admin IPs
set admin_ips {
type ipv4_addr
flags interval
}
# Allow SSH only from admin IPs (if you have a static IP)
iifname "eth0" ip saddr @admin_ips tcp dport 22 accept
# Add an IP to the set at runtime
sudo nft add element inet filter admin_ips { 203.0.113.42 }
# Define a blocklist as a set
set blocklist {
type ipv4_addr
timeout 24h
}
# Block all traffic from blocked IPs
iifname "eth0" ip saddr @blocklist log prefix "blocklist-drop: " counter drop
Logging and Monitoring
nftables logging integrates with the kernel’s audit subsystem. Monitor dropped packets to identify attack patterns:
# Watch dropped packets in real time
sudo journalctl -f -t kernel | grep nftables-drop
# Count dropped packets per rule
sudo nft list ruleset | grep -A2 "counter drop"
# Check set usage statistics
sudo nft list set inet filter ssh_bruteforce
IPv6 Considerations
If your VPS has IPv6 enabled, the inet family handles both IPv4 and IPv6 in the same ruleset. However, you may need to add specific rules for IPv6 ICMP:
# Allow IPv6 neighbor discovery (essential for SLAAC)
ip6 nexthdr icmpv6 icmpv6 type { \
nd-neighbor-solicit, nd-neighbor-advert, \
nd-router-solicit, nd-router-advert \
} accept
Applying and Testing the Ruleset
Always test ruleset changes before applying them permanently:
# Check syntax without applying
sudo nft -c -f /etc/nftables.conf
# Apply the ruleset
sudo nft -f /etc/nftables.conf
# Verify the rules are loaded
sudo nft list ruleset
# Test connectivity from another terminal
ssh your-ip
curl -I https://your-domain.com
# If you lock yourself out, reboot your VPS from the provider panel
# to reset the firewall (nftables is not persistent by default)
Conclusion
nftables provides a modern, efficient firewall for your VPS that can handle everything from basic port filtering to dynamic rate limiting and IP sets. Its atomic rule loading and unified syntax make it safer and easier to manage than the legacy iptables framework. For more information on choosing a VPS provider that gives you full control over your networking stack, visit our VPS hosting guide.

Leave a Reply
You must be logged in to post a comment.