86 lines
3.0 KiB
PHP
86 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
class ASNService
|
|
{
|
|
public static function validateIP($ip, $asn)
|
|
{
|
|
// Remove 'AS' prefix if present for comparison
|
|
$targetAsn = ltrim(strtoupper($asn), 'AS');
|
|
|
|
// Use whois command
|
|
// This command queries Cymru's whois server which is reliable for IP to ASN mapping
|
|
// Format: whois -h whois.cymru.com " -v [IP]"
|
|
|
|
$command = sprintf('whois -h whois.cymru.com " -v %s"', escapeshellarg($ip));
|
|
|
|
// Use proc_open to capture output and potential errors
|
|
$descriptorspec = [
|
|
0 => ["pipe", "r"], // stdin
|
|
1 => ["pipe", "w"], // stdout
|
|
2 => ["pipe", "w"] // stderr
|
|
];
|
|
|
|
$process = proc_open($command, $descriptorspec, $pipes);
|
|
|
|
if (is_resource($process)) {
|
|
$output = stream_get_contents($pipes[1]);
|
|
$errors = stream_get_contents($pipes[2]);
|
|
fclose($pipes[0]);
|
|
fclose($pipes[1]);
|
|
fclose($pipes[2]);
|
|
$return_value = proc_close($process);
|
|
|
|
if ($return_value !== 0 || empty($output)) {
|
|
// Whois command failed, try HTTP API fallback
|
|
// Using ip-api.com (free, no key required for limited use)
|
|
// Format: http://ip-api.com/json/{ip}?fields=status,message,as
|
|
|
|
$apiUrl = "http://ip-api.com/json/" . $ip . "?fields=status,message,as";
|
|
$context = stream_context_create(['http' => ['timeout' => 3]]);
|
|
$apiResponse = @file_get_contents($apiUrl, false, $context);
|
|
|
|
if ($apiResponse !== FALSE) {
|
|
$data = json_decode($apiResponse, true);
|
|
if (isset($data['status']) && $data['status'] === 'success' && isset($data['as'])) {
|
|
// Format example: "AS15169 Google LLC"
|
|
// Extract AS number
|
|
if (preg_match('/AS(\d+)/', $data['as'], $matches)) {
|
|
$foundAsn = $matches[1];
|
|
return $foundAsn === $targetAsn;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If both fail, strictly return false as requested to prevent invalid registrations
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
// Parse output
|
|
// Output example:
|
|
// AS | IP | BGP Prefix | CC | Registry | Allocated | AS Name
|
|
// 15169 | 8.8.8.8 | 8.8.8.0/24 | US | arin | 2000-03-30 | GOOGLE, US
|
|
|
|
$lines = explode("\n", trim($output));
|
|
foreach ($lines as $line) {
|
|
if (strpos($line, 'AS') !== false && strpos($line, 'IP') !== false) {
|
|
continue;
|
|
}
|
|
|
|
$parts = explode('|', $line);
|
|
if (count($parts) >= 1) {
|
|
$foundAsn = trim($parts[0]);
|
|
if ($foundAsn === $targetAsn) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|