From 465191b461e78d2498debdcabfd329ea77c38159 Mon Sep 17 00:00:00 2001 From: Jasper Frumau Date: Tue, 25 Aug 2026 10:15:45 +0700 Subject: [PATCH] Anchor WordPress fail2ban filters to the request field The wordpress_wp_login and wordpress_xmlrpc failregex patterns used an unbounded `.*` after `"POST`, so they matched wp-login.php/xmlrpc.php anywhere later in the access log line -- including the Referer header. Background AJAX requests fired from an open wp-login.php tab (heartbeat API, 2FA plugin polling) carry wp-login.php as their Referer and were counted as failed logins, which can ban a legitimate admin mid-login with the default maxretry of 6. Bound the match with `[^"]*` so it stops at the closing quote of the request field, and require a 200 status. Trellis' nginx `main` log format puts $status directly after "$request", so a genuine failed login logs 200 while a successful one logs a 30x redirect -- the old pattern had no status requirement at all and matched both. --- roles/fail2ban/templates/filters/wordpress-wp-login.conf.j2 | 2 +- roles/fail2ban/templates/filters/wordpress-xmlrpc.conf.j2 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/fail2ban/templates/filters/wordpress-wp-login.conf.j2 b/roles/fail2ban/templates/filters/wordpress-wp-login.conf.j2 index d0f9271098..1de31a3982 100644 --- a/roles/fail2ban/templates/filters/wordpress-wp-login.conf.j2 +++ b/roles/fail2ban/templates/filters/wordpress-wp-login.conf.j2 @@ -1,2 +1,2 @@ [Definition] -failregex = ^ .* "POST .*wp-login\.php +failregex = ^ .* "POST [^"]*wp-login\.php[^"]*" 200 diff --git a/roles/fail2ban/templates/filters/wordpress-xmlrpc.conf.j2 b/roles/fail2ban/templates/filters/wordpress-xmlrpc.conf.j2 index 6d8547146f..e5c01bb090 100644 --- a/roles/fail2ban/templates/filters/wordpress-xmlrpc.conf.j2 +++ b/roles/fail2ban/templates/filters/wordpress-xmlrpc.conf.j2 @@ -1,2 +1,2 @@ [Definition] -failregex = ^ .* "POST .*xmlrpc\.php +failregex = ^ .* "POST [^"]*xmlrpc\.php[^"]*" 200