Fail2Ban for Craft CMS

Installation

Requirements

  • Craft CMS 5.3 or later
  • PHP 8.2 or later
  • fail2ban on the server, if you want the firewall to do the banning — which you do, wherever you can run it. Without it, Pro's built-in blocker enforces the same jails in PHP.

There are no runtime dependencies beyond Craft, no build step and no outbound requests.

Install

composer require justinholtweb/craft-fail2ban
php craft plugin/install fail2ban

Or find Fail2Ban in the Craft Plugin Store and install it from there.

What happens on install

The plugin starts logging straight away, with working defaults:

  • every authentication event that matters is on;
  • lines go to the auth syslog facility and to storage/logs/fail2ban.log;
  • the client address is taken from the socket, not from any header;
  • a copy of every event is kept in the database for 30 days, which is what the control panel reads.

Nothing is banned yet. Banning is fail2ban's job, and fail2ban does not know about any of this until you hand it the filter and jail files.

Hand the files to fail2ban

Go to Fail2Ban → Setup. If that page opens with a Fix these first panel, read it before going any further — each warning there means the jails would ban the wrong address or miss the right one. The most common is a site behind a proxy or CDN; see Client addresses.

The page shows every generated file with a download button. Copy them onto the machine running fail2ban and reload it:

sudo cp craft-*.conf /etc/fail2ban/filter.d/
sudo cp craft.local  /etc/fail2ban/jail.d/
sudo fail2ban-client reload

With shell access on the Craft server itself, one command does the same thing:

sudo php craft fail2ban/configs/write --directory=/etc/fail2ban
sudo fail2ban-client reload

The files are generated from this site's current settings. Change a jail's numbers, the log path or the ignore list, and regenerate.

Prove it works

Before you need it to:

php craft fail2ban/events/test
fail2ban-regex /path/to/storage/logs/fail2ban.log /etc/fail2ban/filter.d/craft-auth.conf
php craft fail2ban/status

events/test writes one line per enabled event type, all naming 203.0.113.7 — an address reserved for documentation, so a test can never ban a real visitor. fail2ban-regex is fail2ban's own tool, and it should report matches. status is one screen: channels, events, jails, and whether every filter still matches the line it was built from.

Then try it for real: sign in with a wrong password from a phone on mobile data, and watch the line arrive.

tail -f storage/logs/fail2ban.log

Editions

Lite is free. Pro is $59 one-off, with an optional $29/year renewal for updates.

LitePro
Failed, unknown, blocked, locked, suspended and cooldown logins✓✓
Invalid tokens, failed elevated sessions, password resets, successful logins✓✓
Syslog, file and database channels✓✓
Blocked usernames and patterns✓✓
Generated filters and jails, and the check that they still match✓✓
Console commands✓✓
User enumeration✓
Probes for /wp-login.php, /.env and the rest✓
404, 403 and 400 logging✓
GraphQL authorization failures✓
Public registrations✓
Built-in blocker, for hosts with no fail2ban✓
Ban notification emails✓