Skip to content

Instantly share code, notes, and snippets.

@Byteflux
Last active September 24, 2021 03:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Byteflux/df76b827085ad97af64f2c352d83d243 to your computer and use it in GitHub Desktop.
Save Byteflux/df76b827085ad97af64f2c352d83d243 to your computer and use it in GitHub Desktop.
<?php
// ip2asn.php?ip=IP_OR_HOSTNAME : Returns a comma-separated list of matching ASNs
// ip2asn.php?asn=AS_NUMBER : Returns the organization name
// ip2asn.php?update=1&token=SECRET_TOKEN : Updates the local database (setup cron to run once a day)
$SECRET_TOKEN = 'ChangeMe';
$TMP_DIR = '/tmp/ip2asn';
$DATA_DIR = '/var/lib/ip2asn';
function remove_recursive($dir, $remove_dir = false) {
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
$delete = ($file->isDir() ? 'rmdir' : 'unlink');
$delete($file->getRealPath());
}
if ($remove_dir) {
rmdir($dir);
}
}
function ip_in_range($ip, $range) {
if (strpos($range, '/') === false) {
$range .= '/32';
}
list($range, $netmask) = explode('/', $range, 2);
$range_decimal = ip2long($range);
$ip_decimal = ip2long($ip);
$wildcard_decimal = pow(2, (32 - $netmask)) - 1;
$netmask_decimal = ~ $wildcard_decimal;
return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal));
}
if (!empty($_GET['update']) && isset($_GET['token']) && $_GET['token'] == $SECRET_TOKEN) {
set_time_limit(0);
if (!file_exists($TMP_DIR)) {
mkdir($TMP_DIR, 0770, true);
} else {
remove_recursive($TMP_DIR);
}
if (!file_exists($DATA_DIR)) {
mkdir($DATA_DIR, 0770, true);
}
$dumps = ['data-used-autnums', 'data-raw-table'];
foreach ($dumps as $dump) {
$fp = fopen("$TMP_DIR/$dump", 'w+');
$ch = curl_init("http://thyme.apnic.net/current/$dump");
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
try {
$error = curl_error($ch);
if (!empty($error)) {
echo "$error\n";
exit(1);
}
} finally {
curl_close($ch);
fclose($fp);
}
}
$index_dirs = ['index', 'index/asn', 'index/prefix'];
foreach ($index_dirs as $index_dir) {
$dir = "$TMP_DIR/$index_dir";
if (!file_exists($dir)) {
mkdir($dir);
}
}
$fp = fopen("$TMP_DIR/data-used-autnums", 'r');
while (($line = fgets($fp)) != null) {
list ($asn, $org) = preg_split('/\s+/', trim($line), 2);
$dir = "$TMP_DIR/index/asn/$asn[0]";
if (!file_exists($dir)) {
mkdir($dir, 0770);
}
file_put_contents("$dir/$asn", $org);
}
fclose($fp);
$fp = fopen("$TMP_DIR/data-raw-table", 'r');
$prefixes = [];
while (($line = fgets($fp)) != null) {
list ($prefix, $asn) = preg_split('/\s+/', trim($line), 2);
$key = explode('.', $prefix)[0];
$prefixes[$key][$prefix] = $asn;
}
fclose($fp);
foreach ($prefixes as $key => $prefix) {
$fp = fopen("$TMP_DIR/index/prefix/$key", 'w+');
foreach ($prefix as $cidr => $asn) {
fwrite($fp, "$cidr $asn\n");
}
fclose($fp);
}
if (file_exists("$DATA_DIR/index")) {
rename("$DATA_DIR/index", "$DATA_DIR/index.old");
}
rename("$TMP_DIR/index", "$DATA_DIR/index");
$remove_dirs = ['index.old', 'cache'];
foreach ($remove_dirs as $remove_dir) {
if (file_exists("$DATA_DIR/$remove_dir")) {
remove_recursive("$DATA_DIR/$remove_dir", true);
}
}
exit;
}
if (isset($_GET['ip'])) {
$ip = gethostbyname($_GET['ip']);
if (preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $ip)) {
$cache_file = "$DATA_DIR/cache/" . str_replace('.', '/', $ip);
if (file_exists($cache_file)) {
readfile($cache_file);
} else {
$key = explode('.', $ip)[0];
$prefix_file = "$DATA_DIR/index/prefix/$key";
if (file_exists($prefix_file)) {
$results = [];
$fp = fopen($prefix_file, 'r');
while (($line = fgets($fp)) != null) {
list ($prefix, $asn) = explode(' ', trim($line), 2);
if (ip_in_range($ip, $prefix)) {
$results[] = $asn;
}
}
fclose($fp);
$cache_dir = dirname($cache_file);
if (!file_exists($cache_dir)) {
mkdir($cache_dir, 0770, true);
}
$output = implode(',', array_unique($results));
file_put_contents($cache_file, $output);
echo $output;
}
}
}
exit;
}
if (isset($_GET['asn']) && ctype_digit($_GET['asn'])) {
$file = "$DATA_DIR/index/asn/{$_GET['asn'][0]}/$_GET[asn]";
if (file_exists($file)) {
readfile($file);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment