Last active
December 15, 2015 04:09
-
-
Save jamesstout/5199181 to your computer and use it in GitHub Desktop.
Script to look up the location of a list of IP addresses. Uses ipinfodb.com. Writes known IP info to a file to prevent repeat lookups.
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 | |
// URL is http://api.ipinfodb.com/v3/ip-city/?key=xxxxxxxxxx&ip=74.125.45.100 | |
/* response should be something like | |
{ | |
"statusCode" : "OK", | |
"statusMessage" : "", | |
"ipAddress" : "180.169.76.237", | |
"countryCode" : "CN", | |
"countryName" : "CHINA", | |
"regionName" : "SHANGHAI", | |
"cityName" : "SHANGHAI", | |
"zipCode" : "-", | |
"latitude" : "31.2222", | |
"longitude" : "121.458", | |
"timeZone" : "+08:00" | |
} | |
Errors include: | |
"statusCode" : "ERROR", | |
"statusMessage" : "Invalid API key.", | |
*/ | |
if (!ini_get('display_errors')) { | |
ini_set('display_errors', 0); | |
} | |
header('Content-type: text/html'); | |
outputHeader(); | |
set_time_limit(0); | |
ini_set('max_execution_time', 300); | |
$curl_error_str; | |
$curl_error_no; | |
$info = array(); | |
$path = dirname(__FILE__); | |
$dodgyIPsFile = $path . '/dodgyIPs.txt'; | |
// get 'new' IPs | |
$newDodgyIPs = getNewDodgyIPs(); | |
//get IPs we have already looked up | |
$dodgyIPsAlreadyDone = readIPInfoFromFile(); | |
// now we need to trim $newDodgyIPs so it only contains truly new IPs | |
$newDodgyIPs = trimDodgyIPs($newDodgyIPs, $dodgyIPsAlreadyDone); | |
try { | |
foreach ($newDodgyIPs as $key => $IP) { | |
//echo "<pre>" .print_r($key,1). " = " .print_r($IP,1)."</pre>"; | |
$response = getIPLocayData($IP); | |
if (is_array($response)) { | |
$info[$key] = $response; | |
} | |
// rate limit for the Ip lookup Web site | |
sleep(1); | |
} | |
// combine new info array with $dodgyIPsAlreadyDone | |
foreach ($info as $key => $val) { | |
// use array_push as the array_diff | |
// in trimDodgyIPs() does not reset the keys | |
array_push($dodgyIPsAlreadyDone, $val ); | |
} | |
// write the updated info array back to the file | |
writeInfoToFile($dodgyIPsAlreadyDone); | |
// if we get here, all is good, let's output a table | |
outputResultsTable($dodgyIPsAlreadyDone); | |
} | |
catch (Exception $ex) { | |
die("ERROR: " . $ex->getMessage()); | |
} | |
exit; | |
function trimDodgyIPs($newDodgyIPs, $dodgyIPsAlreadyDone) { | |
// grab known IPs | |
$knowIPs = array(); | |
foreach ($dodgyIPsAlreadyDone as $k=>$v) { | |
foreach ($v as $column=>$val) { | |
if ($column == "IP") { | |
$knowIPs[] = $val; | |
} | |
} | |
} | |
//echo "<pre> known IPs".print_r($knowIPs, 1)."</pre>"; | |
//echo "<pre> new IPs".print_r($newDodgyIPs, 1)."</pre>"; | |
// get the diff - note keys are not reset | |
$realNewDodgyIPs = array_diff($newDodgyIPs, $knowIPs); | |
//echo "<pre> new IPs".print_r($realNewDodgyIPs, 1)."</pre>"; | |
return $realNewDodgyIPs; | |
} | |
function writeInfoToFile($info) { | |
global $dodgyIPsFile; | |
//seralise the array to store to disk | |
$serializedInfo = serialize_safe($info); | |
// open output file for writing, truncate and in binary mode | |
// binary mode preserves the line endings in the input file | |
// \n for Unix, \r\n for Windows. | |
if (!$handle = fopen($dodgyIPsFile , "w+b")) { | |
die ("Cannot open $dodgyIPsFile"); | |
} | |
// Write $serializedInfo to our opened file. | |
if (fwrite($handle, $serializedInfo) === FALSE) { | |
echo "Cannot write to file ($dodgyIPsFile)\n"; | |
exit; | |
} | |
fclose($handle); | |
} | |
function readIPInfoFromFile() { | |
global $dodgyIPsFile; | |
if (!$lines = file($dodgyIPsFile)) { | |
die ("Cannot open $dodgyIPsFile"); | |
} | |
else { | |
// it's one base 64 encoded line | |
$info = unserialize_safe($lines[0]); | |
//echo "<pre>".print_r($info, 1)."</pre>"; | |
return $info; | |
} | |
} | |
/** | |
* | |
*/ | |
function outputResultsTable($info) { | |
echo '<table id="box-table-a" >'; | |
echo "<thead><tr>"; | |
foreach ($info as $k=>$v) { | |
if ($k > 0) { | |
break; | |
} | |
echo "<th>Count</th>"; | |
foreach ($v as $column=>$val) { | |
if ($column != "IP") echo "<th>$column</th>"; | |
} | |
} | |
echo "</tr></thead><tbody>"; | |
$count=1; | |
foreach ($info as $k=>$v) { | |
echo "<tr>"; | |
echo "<td>$count</td>"; | |
$count++; | |
foreach ($v as $column=>$val) { | |
if ($column != "IP") echo "<td>$val</td>"; | |
} | |
echo "</tr>"; | |
} | |
echo "</tbody></table></body></html>"; | |
} | |
function outputHeader() { | |
$head=<<<EOF | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
<title>Dodgy IP Addresses</title> | |
<style type="text/css"> | |
<!-- | |
@import url("css/style.css"); | |
--> | |
</style> | |
</head> | |
<body> | |
EOF; | |
echo $head; | |
} | |
/** | |
* | |
* | |
* | |
*/ | |
function getIPLocayData($IP) { | |
global $curl_error_str; | |
global $curl_error_no; | |
$IPLookupURL = "http://api.ipinfodb.com/v3/ip-city/?key=xxxxxxx&format=json&ip=" . $IP; | |
$result = CURL($IPLookupURL); | |
// ensure the request succeeded | |
if ($curl_error_no != 0) { | |
throw new Exception("CURL" . $curl_error_str); | |
} | |
/** | |
* For testing various responses | |
* | |
* | |
*/ | |
// test invalid response format | |
//$result = '"statusCode" : "OK", "statusMessage" : "", "ipAddress" : ""}'; | |
// test statusMessage set response format | |
//$result = '{"statusCode" : "ERROR", "statusMessage" : "XXX", "ipAddress" : "180.169.76.237", "countryCode" : "CN", "countryName" : "CHINA"}'; | |
// test statusCode mising response format | |
//$result = '{"statusMessage" : "", "ipAddress" : "180.169.76.237", "countryCode" : "CN", "countryName" : "CHINA"}'; | |
// parse the response data | |
$data = json_decode($result); | |
// ensure response data was a valid JSON string | |
if (!is_object($data)) { | |
throw new Exception('Invalid response data, not JSON object: ' . $result ); | |
} | |
// ensure the expected statusCode is present | |
if (!isset($data->statusCode) ) { | |
throw new Exception('Invalid response data, statusCode missing: ' . $result ); | |
} | |
if ($data->statusCode == "ERROR" || $data->statusCode != "OK" ) { | |
// we have an error, I don't know all the errors, only ERROR | |
throw new Exception("API error: " . (isset($data->statusMessage) ? $data->statusMessage : "UNKNOWN ERROR" )); | |
} | |
// build the response array with the returned data | |
return array( | |
'Country Code' => $data->countryCode, | |
'CountryName' => $data->countryName, | |
'RegionName' => $data->regionName, | |
'City' => $data->cityName, | |
'Zip Code' => $data->zipCode, | |
'Time Zone' => $data->timeZone, | |
'Latitude/Longitude'=> "$data->latitude, $data->longitude", | |
'Google Maps Link' => "<a href=https://maps.google.com/?ll=$data->latitude,$data->longitude > $IP </a>", | |
'IP' => $IP | |
); | |
} | |
function CURL($url, $retries = 3) { | |
global $curl_error_str; | |
global $curl_error_no; | |
$curl = curl_init($url); | |
if (is_resource($curl) === true) { | |
curl_setopt($curl, CURLOPT_FAILONERROR, true); | |
curl_setopt($curl, CURLOPT_TIMEOUT, 15); | |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); | |
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); | |
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); | |
curl_setopt($curl, CURLOPT_NOSIGNAL, 1); | |
curl_setopt($curl, CURLOPT_MAXCONNECTS, 1); | |
// for testing cURl errors | |
//curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 2); | |
$result = false; | |
//echo "<pre>".print_r($curl,1)."</pre>"; | |
while (($result === false) && (--$retries > 0)) { | |
//echo "CURL retries = $retries\n"; | |
$result = curl_exec($curl); | |
} | |
// Check if any error occured | |
if (curl_errno($curl)) { | |
$curl_error_str = curl_error($curl); | |
$curl_error_no = curl_errno($curl); | |
//echo 'Curl error: ' . curl_error($curl); | |
//echo 'Curl error no: ' . curl_errno($curl); | |
} | |
curl_close($curl); | |
//echo "<pre>Closing CURL</pre>"; | |
} | |
else { | |
$curl_error_no = 999; | |
$curl_error_str = "curl_init() failed for $url"; | |
} | |
return $result; | |
} | |
function getNewDodgyIPs() { | |
return array( | |
"108.61.63.165", | |
"114.242.87.141", | |
"114.80.138.6", | |
"115.119.161.62", | |
"116.11.252.194", | |
"116.229.239.189", | |
"117.27.139.8", | |
"118.122.33.160", | |
"118.26.233.211", | |
"119.36.186.44", | |
"121.8.148.61", | |
"121.8.154.28", | |
"122.192.35.240", | |
"122.226.34.150", | |
"123.127.160.102", | |
"123.138.37.73", | |
"123.164.66.216", | |
"123.164.66.219", | |
"124.160.194.27", | |
"124.217.239.87", | |
"124.95.160.148", | |
"125.211.221.97", | |
"150.214.190.39", | |
"157.7.169.57", | |
"178.210.32.14", | |
"180.169.76.237", | |
"180.68.206.92", | |
"190.6.176.20", | |
"190.82.84.203", | |
"198.27.64.56", | |
"200.38.75.72", | |
"202.103.36.43", | |
"202.121.166.203", | |
"202.199.224.25", | |
"202.70.136.23", | |
"202.97.194.171", | |
"210.123.1.169", | |
"211.169.127.86", | |
"212.55.8.177", | |
"218.108.85.245", | |
"218.246.71.229", | |
"218.25.251.19", | |
"218.26.89.179", | |
"218.27.252.7", | |
"218.6.130.215", | |
"221.10.112.134", | |
"221.143.48.248", | |
"221.234.42.9", | |
"222.114.39.171", | |
"222.171.156.100", | |
"222.186.59.219", | |
"222.255.237.26", | |
"222.59.10.6", | |
"222.80.184.46", | |
"223.3.58.122", | |
"37.140.234.126", | |
"58.215.82.148", | |
"60.13.74.23", | |
"60.169.22.118", | |
"60.190.243.250", | |
"60.191.19.2", | |
"60.191.30.92", | |
"60.217.229.252", | |
"61.130.254.91", | |
"61.158.164.59", | |
"61.238.156.106", | |
"61.240.36.1", | |
"61.255.198.241", | |
"61.54.105.38", | |
"61.98.134.14", | |
"66.55.79.29", | |
"67.205.67.147", | |
"77.88.234.171", | |
"80.13.235.11", | |
"84.235.61.72", | |
"86.56.232.218", | |
"88.119.151.2", | |
"89.165.3.186", | |
"94.102.3.151", | |
); | |
} | |
/** | |
* Returns a serialized, base64-encoded string from a PHP object | |
* | |
*/ | |
function serialize_safe($data = null) { | |
return base64_encode(serialize($data)); | |
} | |
/** | |
* Returns a PHP object from a base64-encoded, serialized string | |
* | |
*/ | |
function unserialize_safe($base64_data = '') { | |
return unserialize(base64_decode($base64_data)); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment