Created
October 19, 2015 11:25
-
-
Save thequux/d09cc433b28b3383be5a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// This is designed to be used with the IP list from | |
// https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt | |
// | |
// To use: | |
// $ipset = new IPSet("emerging-Block-IPs.txt"); | |
// if ($ipset->check_ip($_SERVER['REMOTE_ADDR'])) { | |
// // Block the request | |
// } | |
class IPSet { | |
private $blacklist = null; | |
# We don't know whether we're working with 32-bit or 64-bit | |
# integers, so we instead *always* sign-extend from 32-bits. | |
function __construct($blacklist_file) { | |
$this->blacklist = array(); | |
try { | |
$file = fopen($blacklist_file, "r"); | |
if ($file === false) { | |
error_log("Blacklist file not found"); | |
return; | |
} | |
// Read the lines | |
while (($line = fgets($file)) !== false) { | |
// Strip comments and newline | |
$commentStart = strpos($line, '#'); | |
if ($commentStart !== false) { | |
$line = substr($line, 0, $commentStart); | |
} | |
$line = trim($line); | |
if ($line !== "") { | |
$parsed = $this->parse_ip($line); | |
if ($parsed !== false) { | |
//printf("%20s %016x/%08x\n", $line, $parsed[0], $parsed[1]); | |
$this->blacklist []= $parsed; | |
} | |
} | |
} | |
} finally { | |
fclose($file); | |
} | |
} | |
private function parse_ip($cidr) { | |
$slashPos = strpos($cidr, "/"); | |
if ($slashPos === false) { | |
$mask = -1; | |
$ipS = $cidr; | |
} else { | |
// This won't work with a subnet of 0 on 32-bit machines, | |
// but that's fine, because this is intended for use as a | |
// *blacklist*, and blocking a /0 would block everything | |
$mask = -1 << (32 - substr($cidr, $slashPos + 1)); | |
$ipS = substr($cidr, 0, $slashPos); | |
} | |
// Now, parse the IP. First, this will involve breaking it | |
// into octets | |
$octets = explode(".", $ipS); | |
if (count($octets) != 4) { | |
// WTF? This shouldn't happen. | |
// TODO: Throw an error | |
return false; | |
} | |
$ip = $octets[0] - 0; | |
if ($ip >= 128) { | |
$ip -= 256; // treat as signed byte so that it works on | |
// 32-bit PHPs. | |
} | |
// Add the rest of the octets | |
for ($i = 1; $i < 4; $i++) { | |
$ip = ($ip << 8) + $octets[$i]; | |
} | |
return array($ip & $mask, $mask); | |
} | |
public function check_ip($ip) { | |
// returns true if the IP is in the blacklist. | |
list($ip, $ipmask) = $this->parse_ip($ip); | |
foreach ($this->blacklist as $probe) { | |
list($probeIp, $probeMask) = $probe; | |
if (($ip & $probeMask) == $probeIp) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
BTW, this is licensed under your choice of ISC, BSD 2-clause, or MIT licenses. If, for some reason, none of those are acceptable, contact me for a custom license.