WP fail2ban - Version 2.0.0

Version Description

  • Add experimental support for X-Forwarded-For header; see WP_FAIL2BAN_PROXIES
  • Add experimental support for regex-based login blocking; see WP_FAIL2BAN_BLOCKED_USERS
Download this release

Release Info

Developer invisnet
Plugin Icon 128x128 WP fail2ban
Version 2.0.0
Comparing to
See all releases

Code changes from version 1.2.1 to 2.0.0

Files changed (3) hide show
  1. readme.txt +44 -8
  2. wordpress.conf +1 -0
  3. wp-fail2ban.php +53 -5
readme.txt CHANGED
@@ -4,8 +4,8 @@ Author URI: https://charles.lecklider.org/
4
  Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
  Tags: fail2ban, security, syslog, login
6
  Requires at least: 3.4.0
7
- Tested up to: 3.5
8
- Stable tag: 1.2.1
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -38,29 +38,65 @@ Requires PHP 5.3 or later.
38
 
39
  1. Reload or restart `fail2ban`
40
 
41
- There are no options to configure.
42
 
43
  == Frequently Asked Questions ==
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  = Why is fail2ban complaining on my flavour of Linux? =
46
 
47
  Depending on your `fail2ban` configuration, you may need to add a line like:
48
 
49
- `port = http,https`
50
 
51
  to the `[wordpress]` section in `jail.local`.
52
 
53
  == Changelog ==
54
 
 
 
 
 
55
  = 1.2.1 =
56
- Update FAQ.
57
 
58
  = 1.2 =
59
- Fix harmless warning.
60
 
61
  = 1.1 =
62
- Minor cosmetic updates.
63
 
64
  = 1.0 =
65
- Initial release.
 
 
66
 
 
 
4
  Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
  Tags: fail2ban, security, syslog, login
6
  Requires at least: 3.4.0
7
+ Tested up to: 3.6
8
+ Stable tag: 2.0.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
38
 
39
  1. Reload or restart `fail2ban`
40
 
41
+ You may want to set WP_FAIL2BAN_PROXIES and/or WP_FAIL2BAN_BLOCKED_USERS; see the FAQ for details.
42
 
43
  == Frequently Asked Questions ==
44
 
45
+ = WP_FAIL2BAN_PROXIES - what's it all about? =
46
+
47
+ The idea here is to list the IP addresses of the trusted proxies that will appear as the remote IP for the request. When defined:
48
+
49
+ * If the remote address appears in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will log the IP address from the `X-Forwarded-For` header
50
+ * If the remote address does not appear in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will return a 403 error
51
+ * If there's no X-Forwarded-For header, *WPf2b* will behave as if `WP_FAIL2BAN_PROXIES` isn't defined
52
+
53
+ To set `WP_FAIL2BAN_PROXIES`, add something like the following to `wp-config.php`:
54
+
55
+ define('WP_FAIL2BAN_PROXIES','192.168.0.42,192.168.0.43');
56
+
57
+ *WPf2b* doesn't do anything clever with the list so don't add whitespace or CIDR notations.
58
+
59
+ = WP_FAIL2BAN_BLOCKED_USERS - what's it all about? =
60
+
61
+ The bots that try to brute-force WordPress logins aren't that clever (no doubt that will change), but they may only make one request per IP every few hours in an attempt to avoid things like `fail2ban`. With large botnets this can still create significant load.
62
+
63
+ Based on a suggestion from *jmadea*, *WPf2b* now allows you to specify a regex that will shortcut the login process if the requested username matches.
64
+
65
+ For example, putting the following in `wp-config.php`:
66
+
67
+ define('WP_FAIL2BAN_BLOCKED_USERS','^admin$');
68
+
69
+ will block any attempt to log in as `admin` before most of the core WordPress code is run. Unless you go crazy with it, a regex is usually cheaper than a call to the database so this should help keep things running during an attack.
70
+
71
+ *WPf2b* doesn't do anything to the regex other than make it case-insensitive.
72
+
73
  = Why is fail2ban complaining on my flavour of Linux? =
74
 
75
  Depending on your `fail2ban` configuration, you may need to add a line like:
76
 
77
+ port = http,https
78
 
79
  to the `[wordpress]` section in `jail.local`.
80
 
81
  == Changelog ==
82
 
83
+ = 2.0.0 =
84
+ * Add *experimental* support for X-Forwarded-For header; see `WP_FAIL2BAN_PROXIES`
85
+ * Add *experimental* support for regex-based login blocking; see `WP_FAIL2BAN_BLOCKED_USERS`
86
+
87
  = 1.2.1 =
88
+ * Update FAQ.
89
 
90
  = 1.2 =
91
+ * Fix harmless warning.
92
 
93
  = 1.1 =
94
+ * Minor cosmetic updates.
95
 
96
  = 1.0 =
97
+ * Initial release.
98
+
99
+ == Upgrade Notice ==
100
 
101
+ = 2.0.0 =
102
+ This is an experimental release. If your current version is working and you're not interested in the new features, skip this version - wait for 2.1.0. For those that do want to test this release, note that `wordpress.conf` has changed - you'll need to copy it to `fail2ban/filters.d` again.
wordpress.conf CHANGED
@@ -22,6 +22,7 @@ _daemon = wordpress
22
  # Values: TEXT
23
  #
24
  failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
 
25
 
26
  # Option: ignoreregex
27
  # Notes.: regex to ignore. If this regex matches, the line is ignored.
22
  # Values: TEXT
23
  #
24
  failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
25
+ ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
26
 
27
  # Option: ignoreregex
28
  # Notes.: regex to ignore. If this regex matches, the line is ignored.
wp-fail2ban.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: WP fail2ban
4
  Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
  Description: Write all login attempts to syslog for integration with fail2ban.
6
- Version: 1.2.1
7
  Author: Charles Lecklider
8
  Author URI: https://charles.lecklider.org/
9
  License: GPL2
@@ -25,17 +25,65 @@ License: GPL2
25
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
  */
27
 
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  add_action( 'wp_login',
30
  function($user_login, $user)
31
  {
32
- openlog('wordpress('.$_SERVER['HTTP_HOST'].')',LOG_NDELAY|LOG_PID,LOG_AUTH);
33
- syslog(LOG_INFO,"Accepted password for $user_login from {$_SERVER['REMOTE_ADDR']}");
34
  },10,2);
35
  add_action( 'wp_login_failed',
36
  function($username)
37
  {
38
- openlog('wordpress('.$_SERVER['HTTP_HOST'].')',LOG_NDELAY|LOG_PID,LOG_AUTH);
39
- syslog(LOG_NOTICE,"Authentication failure for $username from {$_SERVER['REMOTE_ADDR']}");
40
  });
41
 
3
  Plugin Name: WP fail2ban
4
  Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
  Description: Write all login attempts to syslog for integration with fail2ban.
6
+ Version: 2.0.0
7
  Author: Charles Lecklider
8
  Author URI: https://charles.lecklider.org/
9
  License: GPL2
25
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
  */
27
 
28
+ namespace org\lecklider\charles\wp_fail2ban;
29
 
30
+ function openlog()
31
+ {
32
+ \openlog('wordpress('.$_SERVER['HTTP_HOST'].')',
33
+ LOG_NDELAY|LOG_PID,
34
+ defined(WP_FAIL2BAN_LOG) ? WP_FAIL2BAN_LOG : LOG_AUTH);
35
+ }
36
+
37
+ function bail()
38
+ {
39
+ ob_end_clean();
40
+ header('HTTP/1.0 403 Forbidden');
41
+ header('Content-Type: text/plain');
42
+ exit('Forbidden');
43
+ }
44
+
45
+ function remote_addr()
46
+ {
47
+ $ip = $_SERVER['REMOTE_ADDR'];
48
+
49
+ if (defined('WP_FAIL2BAN_PROXIES')) {
50
+ if (array_key_exists($_SERVER,'HTTP_X_FORWARDED_FOR')) {
51
+ if (in_array($ip, explode(',',WP_FAIL2BAN_PROXIES) )) {
52
+ $ip = (false===($len = strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')))
53
+ ? $_SERVER['HTTP_X_FORWARDED_FOR']
54
+ : substr($_SERVER['HTTP_X_FORWARDED_FOR'],0,$len);
55
+ } else {
56
+ bail();
57
+ }
58
+ }
59
+ }
60
+
61
+ return $ip;
62
+ }
63
+
64
+ if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
65
+ add_action( 'authenticate',
66
+ function($user, $username, $password)
67
+ {
68
+ if (!empty($username) && preg_match('/'.WP_FAIL2BAN_BLOCKED_USERS.'/i', $username)) {
69
+ openlog();
70
+ \syslog(LOG_NOTICE,"Blocked authentication attempt for $username from ".remote_addr());
71
+ bail();
72
+ }
73
+
74
+ return $user;
75
+ },1,3);
76
+ }
77
  add_action( 'wp_login',
78
  function($user_login, $user)
79
  {
80
+ openlog();
81
+ \syslog(LOG_INFO,"Accepted password for $user_login from ".remote_addr());
82
  },10,2);
83
  add_action( 'wp_login_failed',
84
  function($username)
85
  {
86
+ openlog();
87
+ \syslog(LOG_NOTICE,"Authentication failure for $username from ".remote_addr());
88
  });
89