-
Notifications
You must be signed in to change notification settings - Fork 0
/
bruteforcebreaker.php
120 lines (98 loc) · 4.21 KB
/
bruteforcebreaker.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
/**
* RoundCube BruteforceBreaker Plugin
*
* Several consecutive failed logins will ban the IP address for 30 minutes.
*
* @version 1.2
* @author Arthur Hoaro <http://hoa.ro>
* @url http://git.hoa.ro/arthur/rc-plugin-bruteforce-breaker/tree/master/
* @license MIT
*/
class bruteforcebreaker extends rcube_plugin {
private $rc;
private $ipbans_file;
private $data_ban = array('FAILURES'=>array(),'BANS'=>array());
function init(){
$this->rc = rcmail::get_instance();
$this->ipbans_file = $this->home.'/ipbans.php';
$this->add_hook('login_failed', array($this, 'ban_loginFailed'));
$this->add_hook('login_after', array($this, 'ban_loginOk'));
$this->add_hook('authenticate', array($this, 'ban_canLogin'));
}
function load_ipban() {
$this->load_config('config.inc.php.dist');
$this->load_config('config.inc.php');
if (!is_file($this->ipbans_file)) $this->write_ipban();
include $this->ipbans_file;
}
function write_ipban() {
file_put_contents($this->ipbans_file, "<?php\n\$this->data_ban=".var_export( $this->data_ban,true ).";\n?>");
}
// Signal a failed login. Will ban the IP if too many failures:
function ban_loginFailed($args) {
$ip = $_SERVER['REMOTE_ADDR'];
if ( $this->isWhitelisted($ip) ) {
rcube::write_log('bruteforcebreaker', sprintf("Whitelist login for %s.", $ip));
return $args;
}
$this->load_ipban();
if (!isset($this->data_ban['FAILURES'][$ip]))
$this->data_ban['FAILURES'][$ip] = 0;
$this->data_ban['FAILURES'][$ip]++;
if ($this->rc->config->get('bruteforcebreaker_keep_trace', true))
rcube::write_log('bruteforcebreaker', sprintf("Login failed for %s. Number of attemps: %d.", $ip, $this->data_ban['FAILURES'][$ip]));
if ($this->data_ban['FAILURES'][$ip] > ($this->rc->config->get('bruteforcebreaker_nb_attemps', 5) -1 )) {
$this->data_ban['BANS'][$ip] = time() + $this->rc->config->get('bruteforcebreaker_duration', 1800);
if ($this->rc->config->get('bruteforcebreaker_keep_trace', true))
rcube::write_log('bruteforcebreaker', sprintf("IP address banned from login - too many attemps (%s).", $ip));
}
$this->write_ipban();
return $args;
}
// Signals a successful login. Resets failed login counter.
function ban_loginOk($args) {
$ip = $_SERVER['REMOTE_ADDR'];
$this->load_ipban();
unset($this->data_ban['FAILURES'][$ip]);
unset($this->data_ban['BANS'][$ip]);
$this->write_ipban();
if ($this->rc->config->get('bruteforcebreaker_keep_trace', true))
rcube::write_log('bruteforcebreaker', sprintf("Login ok for %s.\n", $ip));
return $args;
}
// Checks if the user CAN login. If 'true', the user can try to login.
function ban_canLogin($args) {
$ip=$_SERVER["REMOTE_ADDR"];
if ( $this->isWhitelisted($ip) )
return $args;
$this->load_ipban();
if (!empty($this->data_ban['BANS'][$ip]) ) {
if( $this->data_ban['BANS'][$ip]<=time()) {
unset($this->data_ban['FAILURES'][$ip]);
unset($this->data_ban['BANS'][$ip]);
$this->write_ipban();
if ($this->rc->config->get('bruteforcebreaker_keep_trace', true))
rcube::write_log('bruteforcebreaker', sprintf("Ban lifted for %s.\n", $ip));
}
else $args['pass'] = '';
}
return $args;
}
function isWhitelisted($ip) {
$this->load_ipban();
$ip = ip2long($ip);
$whitelist = $this->rc->config->get('bruteforcebreaker_whitelist', array());
foreach($whitelist as $whiteIp) {
$ipStart = str_replace('*', '0', $whiteIp);
$ipEnd = str_replace('*', '255', $whiteIp);
$ipStart = ip2long($ipStart);
$ipEnd = ip2long($ipEnd);
if($ip >= $ipStart && $ip <= $ipEnd){
return true;
}
}
return false;
}
}
?>