Design: one inet table, stateful allows, explicit service sets, rate-limited logging of drops. Simple to reason about.
1) Ruleset
# /etc/nftables.conf
table inet filter {
sets {
admin_srcs { type ipv4_addr; flags interval; elements = { 203.0.113.0/24 } }
}
chains {
input {
type filter hook input priority 0;
policy drop;
ct state established,related accept
iif lo accept
# Allow ping (optional)
ip protocol icmp icmp type echo-request limit rate 1/second accept
# SSH from admin subnets only
tcp dport 22 ip saddr @admin_srcs accept
# Web example
tcp dport {80,443} accept
# Log & drop others (rate-limited)
limit rate 10/second log prefix "nft-drop: " group 5
drop
}
forward { type filter hook forward priority 0; policy drop; }
output { type filter hook output priority 0; policy accept; }
}
}
sudo nft -f /etc/nftables.conf
sudo systemctl enable nftables
2) Verify
sudo nft list ruleset
sudo journalctl -g 'nft-drop:' -S -1h