1
|
|
|
<?php |
2
|
|
|
$defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; |
3
|
|
|
|
4
|
|
|
class MemcacheAntiDos |
5
|
|
|
{ |
6
|
|
|
public $cache; |
7
|
|
|
public $rate_limit_this_request = false; |
8
|
|
|
public $rate_limit_api_request = false; |
9
|
|
|
public $rate_limit_site_request = false; |
10
|
|
|
public function __construct($config, &$memcache, $request='') { |
11
|
|
|
$this->cache = $memcache; |
12
|
|
|
// set our config options |
13
|
|
|
$userORip = $_SERVER['REMOTE_ADDR'].@$_SERVER['HTTP_USER_AGENT']; |
14
|
|
|
// prep stuff we need to check this request |
15
|
|
|
$key_md5 = $config['memcache']['keyprefix'].md5($userORip); |
16
|
|
|
$request_data = $this->cache->get($key_md5); |
17
|
|
|
$now = time(); |
18
|
|
|
$max_req_flush = max(array($config['mc_antidos']['flush_seconds_api'],$config['mc_antidos']['flush_seconds_site'])); |
19
|
|
|
// check the request |
20
|
|
|
if (is_array($request_data)) { |
21
|
|
|
// this request key already exists, update it |
22
|
|
|
$request_data['la'] = $now; |
23
|
|
View Code Duplication |
if ($request == 'api') { |
|
|
|
|
24
|
|
|
$request_data['ha'] += 1; |
25
|
|
|
if ($config['mc_antidos']['ajax_hits_additive']) { |
26
|
|
|
$request_data['hn'] += 1; |
27
|
|
|
} |
28
|
|
|
} else { |
29
|
|
|
$request_data['hn'] += 1; |
30
|
|
|
} |
31
|
|
|
// not rate limited yet, update the rest of the object |
32
|
|
|
if (($request_data['hn'] < $config['mc_antidos']['rate_limit_site']) && ($request_data['ha'] < $config['mc_antidos']['rate_limit_api'])) { |
33
|
|
|
if (((($request_data['hnl'] + $config['mc_antidos']['flush_seconds_site']) <= $now) || ($request_data['hal'] + $config['mc_antidos']['flush_seconds_api']) <= $now) || (($request_data['la'] + $max_req_flush) <= $now)) { |
34
|
|
|
// needs to be flushed & updated |
35
|
|
|
$new = $this->getRequestBase(); |
36
|
|
|
$new['key'] = $key_md5; |
37
|
|
|
$new['la'] = $now; |
38
|
|
|
$new['hal'] = ((($request_data['hal'] + $config['mc_antidos']['flush_seconds_api']) <= $now)) ? $now : 1; |
39
|
|
|
$new['hnl'] = ((($request_data['hnl'] + $config['mc_antidos']['flush_seconds_site']) <= $now)) ? $now : 1; |
40
|
|
|
$this->cache->set($key_md5, $new, $config['memcache']['expiration']); |
41
|
|
|
$this->rate_limit_api_request = ($request_data['ha'] >= $config['mc_antidos']['rate_limit_api']) ? true : false; |
42
|
|
|
$this->rate_limit_site_request = ($request_data['hn'] >= $config['mc_antidos']['rate_limit_site']) ? true : false; |
43
|
|
|
} else { |
44
|
|
|
// no flush, just update |
45
|
|
|
$new = $this->getRequestBase(); |
46
|
|
|
$new['key'] = $request_data['key']; |
47
|
|
|
$new['la'] = time(); |
48
|
|
|
$new['ha'] = $request_data['ha']; |
49
|
|
|
$new['hal'] = $request_data['hal']; |
50
|
|
|
$new['hn'] = $request_data['hn']; |
51
|
|
|
$new['hnl'] = $request_data['hnl']; |
52
|
|
|
$this->cache->set($key_md5, $new, $config['memcache']['expiration']); |
53
|
|
|
$this->rate_limit_api_request = ($request_data['ha'] >= $config['mc_antidos']['rate_limit_api']) ? true : false; |
54
|
|
|
$this->rate_limit_site_request = ($request_data['hn'] >= $config['mc_antidos']['rate_limit_site']) ? true : false; |
55
|
|
|
} |
56
|
|
|
} else { |
57
|
|
|
// too many hits, we should rate limit this |
58
|
|
|
$this->rate_limit_api_request = ($request_data['ha'] >= $config['mc_antidos']['rate_limit_api']) ? true : false; |
59
|
|
|
$this->rate_limit_site_request = ($request_data['hn'] >= $config['mc_antidos']['rate_limit_site']) ? true : false; |
60
|
|
|
} |
61
|
|
|
} else { |
62
|
|
|
// doesn't exist for this request_key, create one |
63
|
|
|
$new = $this->getRequestBase(); |
64
|
|
|
$new['key'] = $config['memcache']['keyprefix'].md5($userORip); |
65
|
|
|
$new['la'] = time(); |
66
|
|
View Code Duplication |
if ($request == 'api') { |
|
|
|
|
67
|
|
|
$new['ha'] += 1; |
68
|
|
|
if ($config['mc_antidos']['ajax_hits_additive']) { |
69
|
|
|
$new['hn'] += 1; |
70
|
|
|
} |
71
|
|
|
} else { |
72
|
|
|
$new['hn'] += 1; |
73
|
|
|
} |
74
|
|
|
$this->cache->set($key_md5, $new, $config['memcache']['expiration']); |
75
|
|
|
$this->rate_limit_api_request = false; |
76
|
|
|
$this->rate_limit_site_request = false; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
public function getRequestBase() { |
80
|
|
|
$new = array('key' => '','la' => 0,'hn' => 0,'hnl' => 0,'ha' => 0,'hal' => 0); |
81
|
|
|
return $new; |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.