KnowledgebaseNetworking & DNS › Firewall managers compared — ufw, firewalld, raw nftables

Firewall managers compared — ufw, firewalld, raw nftables

Three competing abstractions sit on top of Linux's netfilter: ufw (Debian/Ubuntu's simple wrapper), firewalld (AlmaLinux's zone-based manager), and raw nftables (the modern backend everything else translates to). Pick one and stay there per box — running two managers that don't know about each other is a fast path to confused rules and accidental lockouts. This article covers what each is best at.

ufw — the simple choice

UFW (Uncomplicated Firewall) is the "I just want to allow some ports" tool. Default on Ubuntu, available on Debian.

apt install ufw

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose

That's the whole vocabulary you need for 90% of cases. To restrict by source IP:

ufw allow from 192.0.2.0/24 to any port 22

Pros: trivial syntax, no learning curve, fine for single-VPS deployments. Cons: limited expressiveness — once you need conditional rules, time-based rules, complex NAT, you're outgrowing it.

firewalld — zones and services

Default on AlmaLinux/RHEL family. Built around the abstraction of "zones" (each network interface lives in a zone, each zone has a default-policy + rules), and "services" (named bundles of rules, like "https" = "tcp/443").

dnf install firewalld
systemctl enable --now firewalld

# Show zones
firewall-cmd --list-all-zones

# Add a service to the default zone (public)
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-port=2222/tcp

# Apply (--permanent writes to disk; --reload applies)
firewall-cmd --reload
firewall-cmd --list-all

Pros: zone model is genuinely useful when you have multiple network interfaces (public + private VPN). Standard tooling on AlmaLinux. Cons: more verbose than ufw for simple use cases.

Raw nftables — when you need it

Skip both abstractions and write nftables rules directly when:

  • You need a feature neither manager exposes (rate-limiting per source IP, conditional rules based on connection state, time-of-day rules, complex NAT).
  • You're building a router or gateway with elaborate forwarding behavior.
  • You want a single declarative config you can put in git and apply atomically.

See the "iptables to nftables migration" article in this category for syntax. The short version:

# /etc/nftables.conf
flush ruleset
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        iif lo accept
        ct state established,related accept
        tcp dport { 22, 80, 443 } accept
    }
}

systemctl enable --now nftables

Which one for which scenario

Scenario Pick
Personal/hobby VPS on Debian/Ubuntu, "open these 3 ports"ufw
AlmaLinux production VPSfirewalld (default + integrated with selinux/cockpit)
PBX VPS (FreePBX® manages its own firewall via Sysadmin)Whatever FreePBX wants; don't fight it
Multi-VPS fleet with shared firewall policyRaw nftables in git, deployed via your config-mgmt tool
Gateway / router VPS with NAT + forwardingRaw nftables

The fail2ban relationship

fail2ban detects abusive traffic (SSH brute force, web scrapers, SIP scanners) and adds firewall rules to block the sources. It backends to whichever firewall manager is active:

  • With ufw: banaction = ufw in jail.local.
  • With firewalld: banaction = firewallcmd-ipset (faster than per-IP rules).
  • With nftables directly: banaction = nftables-multiport.

Get this wrong and fail2ban inserts rules that don't take effect (or that disappear when you reload your firewall). Match the banaction to your active manager.

Don't run two at once

The most common cause of "I changed my firewall and now nothing works" is running both ufw AND firewalld, or having both nftables.service and ufw enabled. They all generate rules in the same kernel netfilter tables; the order of rule loading determines what wins, and that order is non-obvious.

# Check what's enabled
systemctl is-enabled ufw nftables firewalld 2>/dev/null

# Disable the ones you're not using
systemctl disable --now ufw       # if using firewalld
systemctl disable --now firewalld # if using ufw

The safety drill

Before applying any new firewall config:

# 1. Schedule a delayed reset
echo "ufw --force reset" | at now + 5 minutes

# 2. Apply your changes
ufw allow 9000/tcp
# ... whatever else ...

# 3. Verify from a SEPARATE SSH session that you can still get in
# 4. If good: cancel the safety reset
atrm <jobid-shown-by-at>

Same pattern works with nftables via nft -f /etc/nftables.conf.backup in the safety job. If you DO get locked out, the LYLIX browser console bypasses the network — log in there and fix the rules.

Also Read

« « Back

Powered by WHMCompleteSolution