Fail2Ban for Craft CMS

Troubleshooting

Start with one command. It answers most of what follows:

php craft fail2ban/status

It lists the channels and whether each one works, every event type and whether it is on, the jail numbers, anything under Fix these first, and whether every filter still matches its line.

Nothing is being logged

  • Is it on? status shows Enabled. The master switch turns off logging and blocking alike.
  • Is the event type on? auth.logout, http.badRequest and user.registered are off by default, and every Pro type shows pro on a Lite install.
  • Are you testing from an ignored address? Anything in ignoreIps is never logged. That includes 127.0.0.1, so a curl from the server itself writes nothing.
  • Is a channel broken? status prints BROKEN with the reason. Usually the log file's directory is not writable by the web server user.
  • Is the request over the limit? One request writes at most maxEventsPerRequest events.

php craft fail2ban/events/test bypasses the first and third of those. If it writes lines and a real failed login does not, look at the address the login came from.

Lines are logged, but nothing is banned

Work through these in order. Each one rules out the next.

  1. Does the filter match the file?

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

    No matches means fail2ban has an old filter. Regenerate it from Setup and copy it again.

  2. Is the jail running?

    sudo fail2ban-client status
    sudo fail2ban-client status craft-auth
    

    A jail missing from the first list was not loaded. sudo fail2ban-client -d prints the parsed configuration and any error.

  3. Is the jail reading the right file? The File list in status craft-auth should name the plugin's log. The generated jail points at the file channel when it is on. When it is off, the path is a guess at where your syslog goes, and Setup says so.

  4. Is the attacker below the threshold? craft-auth bans on the fifth failure in ten minutes. Four wrong passwords followed by a right one is a colleague.

  5. Is the address ignored by fail2ban itself? Check ignoreip in /etc/fail2ban/jail.local as well as the generated craft.local.

Syslog lines never arrive

Some hosts send auth to /var/log/secure, some only to the journal, and some containers discard syslog entirely. Turn on the file channel and let the jail read that. It is the one path the plugin can state with certainty.

If you do use syslog with rsyslog, rsyslog escapes control characters as #012. That is harmless: the plugin removes them before they get that far.

fail2ban refuses to start after copying the files

  • backend = systemd and a logpath in the same jail start without complaint and read nothing. The generated jail never writes both. If you merged it into your own jail.local, check that yours doesn't either.
  • % in a value is ConfigParser interpolation, and fail2ban stops with a stack trace. The plugin escapes it in the log path. If you edited the generated file by hand, double it: %%.

The wrong address is being banned

If every visitor is banned at once, the site is behind a proxy, load balancer or CDN, and the plugin is logging the proxy's address. Setup and status show this under Fix these first. See Client addresses. Unban the proxy first:

sudo fail2ban-client set craft-auth unbanip 10.0.0.5
sudo fail2ban-client set craft-hard unbanip 10.0.0.5

If the address is right but the person is innocent, look at which event banned them in Events:

  • auth.blockedUser with a name that looks real usually means a pattern is too broad. Patterns match anywhere in the name, so test catches contest@example.com. Anchor it: ^test$.
  • auth.enumeration from an office means several people behind one address mistyped their names in the same five minutes. Add the office to ignoreIps or raise enumerationThreshold.
  • http.notFound means a broken link or missing image is being requested over and over. Fix the link, or raise the craft-flood numbers.

You have locked yourself out

From fail2ban:

sudo fail2ban-client set craft-auth unbanip 198.51.100.4

From the built-in blocker (Pro):

php craft fail2ban/bans/remove 198.51.100.4

Then add your office or VPN address to ignoreIps, and regenerate the jail so fail2ban gets it too.

If enforceBlockedUsernames is on and your own account is on the list, the login fails exactly like a wrong password. That's deliberate. Turn enforcement off in config/fail2ban.php, sign in, and rename the account.

A filter stopped matching after an update

php craft fail2ban/configs/verify

The filters are generated from the same templates as the log lines, so after an update the plugin's own filters always match. Copies made from an older version may not. Regenerate and copy again after every update that mentions the log format in the changelog.

The full-page cache stopped hitting

It shouldn't have. Nothing on the 404 path starts a session, because a session means a Set-Cookie header, and a Set-Cookie on every 404 is a cache that never serves a hit. The plugin checks for a signed-in user only when a session is already open. If you are seeing Set-Cookie on anonymous responses, disable the plugin briefly to confirm it is the cause. If it is, that is a bug. Please report it.