Validate if an IP is banned using memcached
* Requirement: how to install memcached in Ubuntu
The most common way to validate if an IP is banned from a website will be to execute a query in the database and look if that IP is banned or not. Although this is a good implementation, you might experience a decrease of performance on your site. The solution: "memcached" the result.
By using memcached, these records will be retrieved very fast and therefore increase the performance of your site.
First, let's create a simple singleton class that extends the Memcache object.
// file: IpCache.class.php class IpCache extends Memcache { const IP_GOOD = 0; const IP_BANNED = 1; private static $instance = NULL; private function __construct() { } public function __destruct() { $this->close(); } public static function getInstance() { if(!is_object(self::$instance)) { self::$instance = new IpCache; self::$instance->addServer('127.0.0.1', 11211) or throw new Exception('Cannot connect to memcached'); } return self::$instance; } public function check($ip) { return $this->get(ip2long($ip)); } public function save($ip, $banned) { $this->set(ip2long($ip), $banned); } }
Now let's create the script to verify if the IP is banned
// file: index.php require('IpCache.class.php'); $ip = $_SERVER['REMOTE_ADDR']; $MemCache = IpCache::getInstance(); $result = $MemCache->check($ip); // if the record does not exists in memcache, add it if($result === FALSE) { /* Do some sql query to check if the IP is banned and use IpCache::IP_BANNED OR IpCache::IP_GOOD */ $t = $MemCache->save($ip, IpCache::IP_BANNED); // or $t = $MemCache->save($ip, IpCache::IP_GOOD); } if($result === IpCache::IP_BANNED) { header('location: http://www.bookofzeus.com'); die(); } /* Load the rest of the page */
Once an Ip is added to memcached, it will stay (unless there's an expiration time or the server reboot) in the system. So if you added a good Ip to a blacklist of Ips and you need to move it to a white list, you will need to use the following code:
// file: admin/memcache-delete.php require('IpCache.class.php'); $ip = '1.1.1.1'; // or can get it from the _GET or _POST $value = 0; // Not Banned $MemCache = IpCache::getInstance(); $MemCache->delete(ip2long($ip)); $MemCache->set(ip2long($ip), $value);
Done!