Security

Combining Fail2ban with UFW and firewalld for Layered Defense

Fail2ban bans IPs with its own rules by default. Point its ban actions at UFW or firewalld so every ban lands in the firewall you already manage and audit.

AdvancedLinux server5 min read

Combining Fail2ban with UFW or firewalld puts every ban into the same ruleset your firewall already manages, instead of a private chain you never look at. You keep one place to audit, one policy to reason about, and bans that survive a firewall reload. This guide points Fail2ban's ban actions at UFW and firewalld, adds a safe whitelist, and shows how to prove a ban actually landed.

Before you start

  • A Linux VPS with root or sudo access. Examples assume you log in as deploy and prefix commands with sudo.
  • Fail2ban installed and running. If it is not, start with Protect SSH from brute-force attacks with Fail2ban.
  • One firewall in charge: UFW on Ubuntu 22.04/24.04 and Debian 12, firewalld on AlmaLinux 8–9 and Rocky 8–9. Running both at once is a common source of confusing results.
  • A second way in — the browser console in your VPS provider's control panel — in case a ban locks you out.

Check what you have before changing anything:

Bash
fail2ban-client -V
sudo ufw status verbose    # Ubuntu and Debian
sudo firewall-cmd --state  # AlmaLinux and Rocky

Warning: Changing banaction restarts Fail2ban and clears existing bans. Do it from a session you can afford to lose, and keep the console open in another tab.

How Fail2ban ban actions reach the firewall

Fail2ban never edits firewall rules directly. A jail calls an action, and that action runs a script from /etc/fail2ban/action.d/. The default banaction is usually iptables-multiport or nftables-multiport on Debian and Ubuntu, and firewallcmd-ipset or firewallcmd-rich-rules on the RHEL family.

That distinction matters. A ban inserted by iptables-multiport lives in Fail2ban's own chain, so ufw status will not show it and ufw reload can wipe it. Pointing the action at the firewall's own tooling fixes both problems.

See what you are using now:

Bash
sudo fail2ban-client -d | grep -i banaction
grep -r "banaction" /etc/fail2ban/jail.local /etc/fail2ban/jail.d/ 2>/dev/null

Combining Fail2ban with UFW and firewalld

Set the action once in the [DEFAULT] section of jail.local so every jail inherits it. Keep the file small and let the defaults do the rest.

UFW on Ubuntu and Debian

INI
# /etc/fail2ban/jail.local
[DEFAULT]
banaction = ufw
banaction_allports = ufw

The ufw action inserts a deny rule for the offending address. Reload and inspect:

Bash
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
sudo ufw status numbered

You should see a DENY IN line for the banned address, placed above your allow rules. Fail2ban inserts at the top, so the ban beats a broad allow rule. That is useful, and it is also why a bad ban hurts.

Tip: UFW's own limit option and Fail2ban solve different problems. UFW rate-limits connections per address; Fail2ban reads logs and bans on behaviour. Running both is fine — see Advanced UFW rate limiting to prevent brute force attacks.

firewalld on AlmaLinux and Rocky

Use the firewalld rich-rule actions. The multiport variant blocks only the ports the jail watches; the allports variant blocks the address everywhere.

INI
# /etc/fail2ban/jail.local
[DEFAULT]
banaction = firewallcmd-rich-rules[actiontype=<multiport>]
banaction_allports = firewallcmd-rich-rules[actiontype=<allports>]

Apply and inspect:

Bash
sudo systemctl restart fail2ban
sudo firewall-cmd --list-rich-rules
sudo firewall-cmd --permanent --list-rich-rules

Bans added this way are runtime rules. A firewall-cmd --reload clears them, and Fail2ban re-applies them from the log on the next match. If you need bans to persist across reloads, use the permanent variant of the action. The trade-offs are covered in Use Fail2ban with firewalld or nftables ban actions.

If you run plain nftables without firewalld, use nftables-multiport and keep your rules in a table Fail2ban can write to. See nftables: Complex Rule Chaining for Stateful Traffic Filtering.

Whitelist before you ban

A layered setup bans fast, so whitelist anything you cannot lose: your office address, your monitoring host, your backup server.

INI
# /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w

bantime.increment makes repeat offenders serve progressively longer bans, which is the whole point of layering. Tune the base values in Configure Fail2ban jails: bantime, findtime and maxretry in jail.local.

Warning: ignoreip entries bypass every jail. Never add a wide range such as 203.0.113.0/24 unless you control every address in it.

Check it works

Ban a test address from the command line, then look at the firewall itself.

Bash
sudo fail2ban-client set sshd banip 203.0.113.10
sudo ufw status | grep 203.0.113.10          # UFW
sudo firewall-cmd --list-rich-rules          # firewalld
sudo fail2ban-client get sshd banip

Then confirm the reverse path works and the rule disappears:

Bash
sudo fail2ban-client set sshd unbanip 203.0.113.10
sudo ufw status | grep 203.0.113.10   # should print nothing

If the address shows in fail2ban-client status sshd but not in the firewall, the action is not reaching the firewall tool. Read the Fail2ban log:

Bash
sudo tail -n 50 /var/log/fail2ban.log

Troubleshooting

  • Ban appears in Fail2ban but not in ufw status — banaction is still iptables-multiport. Set banaction = ufw in [DEFAULT] of jail.local and restart Fail2ban.
  • Bans vanish after ufw reload or firewall-cmd --reload — the firewall rebuilt its ruleset. Re-apply with sudo fail2ban-client reload, or switch to a permanent firewalld action.
  • You locked yourself out — connect through the browser console in your VPS provider's control panel, then remove your own address from the ban list. The full procedure is in Check banned IPs and unban an address in Fail2ban.
  • Real users keep getting banned — the filter is too broad for your traffic. See Fail2ban False Positive Resolution: Fine-Tuning Jails and Timeouts.
  • Nothing is ever banned — the jail is disabled or the log path is wrong. Work through Fail2ban not banning? Common causes and fixes.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.