'Domain-Parameter fehlt']); exit; } $domain = extractRootDomain($domain); if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\-]*\.[a-zA-Z]{2,}$/', $domain)) { http_response_code(400); echo json_encode(['error' => 'Ungültiges Domain-Format']); exit; } $startTime = microtime(true); $whoisData = performWhoisLookup($domain); $queryTime = round((microtime(true) - $startTime) * 1000, 2); if ($whoisData === null) { http_response_code(500); echo json_encode(['error' => 'WHOIS-Abfrage fehlgeschlagen']); exit; } echo json_encode([ 'success' => true, 'domain' => $domain, 'query_time_ms' => $queryTime, 'timestamp' => date('Y-m-d H:i:s'), 'whois' => $whoisData ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); function extractRootDomain(string $domain): string { $domain = strtolower($domain); $domain = preg_replace('/^(https?:\/\/)?(www\.)?/', '', $domain); $domain = explode('/', $domain)[0]; $parts = explode('.', $domain); if (count($parts) > 2) { return implode('.', array_slice($parts, -2)); } return $domain; } function performWhoisLookup(string $domain): ?array { $whoisRaw = whoisViaSocket($domain); if (empty($whoisRaw) && function_exists('shell_exec')) { $escapedDomain = escapeshellarg($domain); $whoisRaw = @shell_exec("whois {$escapedDomain} 2>/dev/null"); } if (empty($whoisRaw)) { return null; } return parseWhoisData($whoisRaw, $domain); } function whoisViaSocket(string $domain): ?string { $whoisServer = getWhoisServer($domain); if (!$whoisServer) { return null; } $result = queryWhoisServer($whoisServer, $domain); if ($result && preg_match('/Registrar WHOIS Server:\s*(\S+)/i', $result, $matches)) { $referralServer = trim($matches[1]); if ($referralServer && $referralServer !== $whoisServer) { $referralResult = queryWhoisServer($referralServer, $domain); if ($referralResult) { $result = $referralResult; } } } return $result; } function queryWhoisServer(string $server, string $domain): ?string { $port = 43; $timeout = 10; $socket = @fsockopen($server, $port, $errno, $errstr, $timeout); if (!$socket) { return null; } stream_set_timeout($socket, $timeout); fwrite($socket, $domain . "\r\n"); $response = ''; while (!feof($socket)) { $response .= fread($socket, 8192); } fclose($socket); return !empty($response) ? $response : null; } function getWhoisServer(string $domain): ?string { $parts = explode('.', $domain); $tld = strtolower(end($parts)); $whoisServers = [ 'com' => 'whois.verisign-grs.com', 'net' => 'whois.verisign-grs.com', 'org' => 'whois.pir.org', 'info' => 'whois.afilias.net', 'biz' => 'whois.biz', 'name' => 'whois.nic.name', 'mobi' => 'whois.dotmobiregistry.net', 'pro' => 'whois.registrypro.pro', 'aero' => 'whois.aero', 'asia' => 'whois.nic.asia', 'cat' => 'whois.nic.cat', 'coop' => 'whois.nic.coop', 'edu' => 'whois.educause.edu', 'gov' => 'whois.dotgov.gov', 'int' => 'whois.iana.org', 'jobs' => 'whois.nic.jobs', 'mil' => 'whois.nic.mil', 'museum' => 'whois.museum', 'post' => 'whois.dotpostregistry.net', 'tel' => 'whois.nic.tel', 'travel' => 'whois.nic.travel', 'xxx' => 'whois.nic.xxx', 'app' => 'whois.nic.google', 'dev' => 'whois.nic.google', 'page' => 'whois.nic.google', 'blog' => 'whois.nic.blog', 'cloud' => 'whois.nic.cloud', 'shop' => 'whois.nic.shop', 'store' => 'whois.nic.store', 'online' => 'whois.nic.online', 'site' => 'whois.nic.site', 'website' => 'whois.nic.website', 'tech' => 'whois.nic.tech', 'io' => 'whois.nic.io', 'co' => 'whois.nic.co', 'me' => 'whois.nic.me', 'tv' => 'whois.nic.tv', 'cc' => 'ccwhois.verisign-grs.com', 'ws' => 'whois.website.ws', 'de' => 'whois.denic.de', 'at' => 'whois.nic.at', 'ch' => 'whois.nic.ch', 'li' => 'whois.nic.li', 'uk' => 'whois.nic.uk', 'fr' => 'whois.nic.fr', 'it' => 'whois.nic.it', 'es' => 'whois.nic.es', 'pt' => 'whois.dns.pt', 'nl' => 'whois.domain-registry.nl', 'be' => 'whois.dns.be', 'pl' => 'whois.dns.pl', 'cz' => 'whois.nic.cz', 'sk' => 'whois.sk-nic.sk', 'hu' => 'whois.nic.hu', 'ro' => 'whois.rotld.ro', 'bg' => 'whois.register.bg', 'hr' => 'whois.dns.hr', 'si' => 'whois.register.si', 'rs' => 'whois.rnids.rs', 'gr' => 'grwhois.ics.forth.gr', 'dk' => 'whois.punktum.dk', 'se' => 'whois.iis.se', 'no' => 'whois.norid.no', 'fi' => 'whois.fi', 'ie' => 'whois.iedr.ie', 'eu' => 'whois.eu', 'lu' => 'whois.dns.lu', 'ru' => 'whois.tcinet.ru', 'ua' => 'whois.ua', 'us' => 'whois.nic.us', 'ca' => 'whois.cira.ca', 'mx' => 'whois.mx', 'br' => 'whois.registro.br', 'ar' => 'whois.nic.ar', 'au' => 'whois.auda.org.au', 'nz' => 'whois.srs.net.nz', 'jp' => 'whois.jprs.jp', 'kr' => 'whois.kr', 'cn' => 'whois.cnnic.cn', 'in' => 'whois.registry.in', 'sg' => 'whois.sgnic.sg', 'hk' => 'whois.hkirc.hk', 'tw' => 'whois.twnic.net.tw', 'za' => 'whois.registry.net.za', ]; if (count($parts) >= 2) { $sld = $parts[count($parts) - 2]; $combinedTld = $sld . '.' . $tld; $secondLevelTlds = [ 'co.uk' => 'whois.nic.uk', 'org.uk' => 'whois.nic.uk', 'me.uk' => 'whois.nic.uk', 'com.au' => 'whois.auda.org.au', 'net.au' => 'whois.auda.org.au', 'org.au' => 'whois.auda.org.au', 'co.nz' => 'whois.srs.net.nz', 'com.br' => 'whois.registro.br', ]; if (isset($secondLevelTlds[$combinedTld])) { return $secondLevelTlds[$combinedTld]; } } return $whoisServers[$tld] ?? 'whois.iana.org'; } function parseWhoisData(string $raw, string $domain): array { $data = [ 'raw' => $raw, 'parsed' => [ 'domain_name' => $domain, 'registrar' => null, 'registrar_url' => null, 'creation_date' => null, 'expiration_date' => null, 'updated_date' => null, 'status' => [], 'nameservers' => [], 'dnssec' => null, ] ]; $lines = explode("\n", $raw); foreach ($lines as $line) { $line = trim($line); if (empty($line) || strpos($line, '%') === 0 || strpos($line, '#') === 0) { continue; } if (strpos($line, ':') !== false) { list($key, $value) = array_map('trim', explode(':', $line, 2)); $keyLower = strtolower($key); if (strpos($keyLower, 'registrar') !== false && strpos($keyLower, 'abuse') === false && strpos($keyLower, 'url') === false) { if (empty($data['parsed']['registrar'])) { $data['parsed']['registrar'] = $value; } } if (strpos($keyLower, 'registrar') !== false && strpos($keyLower, 'url') !== false) { $data['parsed']['registrar_url'] = $value; } if (preg_match('/(creation|created|registered)/i', $keyLower) && strpos($keyLower, 'registrar') === false) { if (empty($data['parsed']['creation_date'])) { $data['parsed']['creation_date'] = $value; } } if (preg_match('/(expir|paid-till)/i', $keyLower)) { if (empty($data['parsed']['expiration_date'])) { $data['parsed']['expiration_date'] = $value; } } if (preg_match('/(updated|modified|changed)/i', $keyLower) && strpos($keyLower, 'registrar') === false) { if (empty($data['parsed']['updated_date'])) { $data['parsed']['updated_date'] = $value; } } if (preg_match('/(status|state)/i', $keyLower) && !empty($value)) { $data['parsed']['status'][] = $value; } if (preg_match('/^(name.?server|nserver)/i', $keyLower) && !empty($value)) { $ns = strtolower(explode(' ', $value)[0]); if (!in_array($ns, $data['parsed']['nameservers'])) { $data['parsed']['nameservers'][] = $ns; } } if (strpos($keyLower, 'dnssec') !== false) { $data['parsed']['dnssec'] = $value; } } } $data['parsed']['status'] = array_unique($data['parsed']['status']); return $data; }