'IP-Parameter fehlt']); exit; } $isIPv4 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); $isIPv6 = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); if (!$isIPv4 && !$isIPv6) { http_response_code(400); echo json_encode(['error' => 'Ungültiges IP-Format']); exit; } $startTime = microtime(true); $result = performReverseLookup($ip, $isIPv6 ? 'IPv6' : 'IPv4'); $queryTime = round((microtime(true) - $startTime) * 1000, 2); echo json_encode([ 'success' => true, 'ip' => $ip, 'ip_version' => $isIPv6 ? 'IPv6' : 'IPv4', 'query_time_ms' => $queryTime, 'timestamp' => date('Y-m-d H:i:s'), 'result' => $result ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); function performReverseLookup(string $ip, string $version): array { $result = [ 'hostname' => null, 'ptr_record' => null, 'additional_info' => [] ]; $hostname = @gethostbyaddr($ip); if ($hostname && $hostname !== $ip) { $result['hostname'] = $hostname; $forwardIp = gethostbyname($hostname); $result['forward_verified'] = ($forwardIp === $ip); $result['additional_info'] = getHostInfo($hostname); } else { $result['error'] = 'Kein PTR-Record gefunden'; } $ptrRecord = getPtrRecord($ip, $version); if ($ptrRecord) { $result['ptr_record'] = $ptrRecord; } $result['ip_info'] = getIpInfo($ip); return $result; } function getPtrRecord(string $ip, string $version): ?string { if ($version === 'IPv4') { $parts = array_reverse(explode('.', $ip)); $ptrDomain = implode('.', $parts) . '.in-addr.arpa'; } else { $expanded = expandIPv6($ip); $nibbles = str_replace(':', '', $expanded); $reversed = implode('.', array_reverse(str_split($nibbles))); $ptrDomain = $reversed . '.ip6.arpa'; } $records = @dns_get_record($ptrDomain, DNS_PTR); if ($records && !empty($records[0]['target'])) { return $records[0]['target']; } return null; } function expandIPv6(string $ip): string { if (strpos($ip, '::') !== false) { $parts = explode('::', $ip); $left = $parts[0] ? explode(':', $parts[0]) : []; $right = isset($parts[1]) && $parts[1] ? explode(':', $parts[1]) : []; $missing = 8 - count($left) - count($right); $middle = array_fill(0, $missing, '0000'); $all = array_merge($left, $middle, $right); } else { $all = explode(':', $ip); } $all = array_map(function($segment) { return str_pad($segment, 4, '0', STR_PAD_LEFT); }, $all); return implode(':', $all); } function getHostInfo(string $hostname): array { $info = []; $parts = explode('.', $hostname); $tld = end($parts); $info['tld'] = $tld; $providerPatterns = [ 'amazonaws.com' => 'Amazon AWS', 'googleusercontent.com' => 'Google Cloud', 'cloudfront.net' => 'Amazon CloudFront', 'azure' => 'Microsoft Azure', 'hetzner' => 'Hetzner', 'ovh' => 'OVH', 'digitalocean' => 'DigitalOcean', 'linode' => 'Linode', 'vultr' => 'Vultr', 'contabo' => 'Contabo', 'netcup' => 'Netcup', 'strato' => 'Strato', 'ionos' => 'IONOS', '1und1' => '1&1', 'telekom' => 'Deutsche Telekom', 'vodafone' => 'Vodafone', ]; foreach ($providerPatterns as $pattern => $provider) { if (stripos($hostname, $pattern) !== false) { $info['provider'] = $provider; break; } } return $info; } function getIpInfo(string $ip): array { $info = [ 'type' => 'unknown' ]; if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { if (preg_match('/^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/', $ip)) { $info['type'] = 'private'; } elseif (preg_match('/^(127\.)/', $ip)) { $info['type'] = 'loopback'; } else { $info['type'] = 'public'; } } else { if (preg_match('/^(fc|fd)/i', $ip)) { $info['type'] = 'private'; } elseif (preg_match('/^::1$/', $ip) || preg_match('/^fe80:/i', $ip)) { $info['type'] = 'loopback/link-local'; } else { $info['type'] = 'public'; } } return $info; }