What you will achieve
Understand which firewall stack your distro uses — legacy iptables, nftables backend, or firewalld — so rules you copy from tutorials actually apply.
1) Check active backend
sudo nft list ruleset
sudo iptables -L -n -v
update-alternatives --display iptables
Debian/Ubuntu often ship iptables-nft compatibility; Fedora defaults to nftables via firewalld.
2) UFW (Ubuntu abstraction)
sudo ufw status verbose
sudo ufw allow 443/tcp
sudo ufw enable
UFW generates nftables/iptables rules underneath — good for simple host firewalls.
3) Direct nftables example
sudo nft add table inet filter
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input tcp dport 22 accept
4) firewalld (RHEL/Fedora)
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Verify
sudo ss -tlnp
sudo nft list ruleset | head
5) Persist nftables rules
sudo nft list ruleset > /etc/nftables.conf
sudo systemctl enable --now nftables
6) iptables-legacy vs nft migration
sudo update-alternatives --config iptables
Legacy tutorials using iptables -A INPUT may silently target different backends. Pick one stack per host.
7) Debugging dropped packets
sudo nft add rule inet filter input counter drop
sudo nft list ruleset | grep counter
Increment counters tell you which rule blocks traffic. For UFW: sudo ufw logging on and watch /var/log/ufw.log.
Docker and firewall interaction
Docker inserts its own iptables/nft rules. Custom rules may need to run after Docker starts or use Docker's iptables: false in daemon.json — advanced and easy to break; document carefully.
8) IPv6 do not forget
sudo ip6tables -L
sudo ufw status verbose
Opening TCP/22 on IPv4 only while IPv6 is wide open is a classic lockout-avoidance failure mode — secure both families.
Prerequisites
Sudo, understanding of inbound vs outbound policy, and list of ports your services need (SSH 22, HTTP 80, HTTPS 443). Console access before enabling default-drop rules on remote VPS.
List listening ports first
sudo ss -tulpn
Firewall rules should mirror actual listeners — opening 3306 when MySQL binds localhost only wastes attack surface if you later misconfigure bind-address.
fail2ban integration
fail2ban inserts ban rules into active firewall backend — verify banaction matches nftables vs iptables on your distro.
Logging dropped packets
sudo nft add rule inet filter input limit rate 5/second burst 10 log prefix "DROP: "Rate-limited log avoids journal flood during scan — correlate with fail2ban or manual IP block decisions.