Whois 協定可查詢域名註冊資訊。不同頂級域名 (TLD) 由不同註冊局管理,查詢伺服器各異。本文提供一個完整的 whoisQuery() 函式,內建常見 TLD 伺服器對照表、自動解析域名後綴、支援快取與錯誤處理,並說明現代 RDAP 替代方案。
<?php
/**
* Whois 域名查詢
*
* @param string $domain 完整域名 (含或不含 www./https://)
* @param int $timeout 連線逾時秒數
* @return array ['raw' => 原始回應, 'available' => 是否可註冊, 'parsed' => 解析後關鍵欄位]
* @throws Exception 查詢失敗
*/
function whoisQuery(string $domain, int $timeout = 10): array {
// 1. 正規化域名
$domain = strtolower(trim($domain));
$domain = preg_replace('~^https?://~i', '', $domain);
$domain = preg_replace('~^www\.~i', '', $domain);
$domain = explode('/', $domain)[0]; // 取第一段
$domain = trim($domain);
if (!preg_match('~^[a-z0-9.-]+\.[a-z]{2,}$~i', $domain)) {
throw new Exception("無效域名格式: $domain");
}
// 2. 取得 TLD (頂級域名)
$parts = explode('.', $domain);
$tld = end($parts); // 簡易取最後一段,實務建議用 Public Suffix List
// 3. TLD -> Whois 伺服器對照表 (部分常見)
$servers = [
// 通用頂級域
'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',
'pro' => 'whois.registrypro.pro',
'xyz' => 'whois.nic.xyz',
'top' => 'whois.nic.top',
'club' => 'whois.nic.club',
'online'=> 'whois.nic.online',
'site' => 'whois.nic.site',
// 國家代碼頂級域
'cn' => 'whois.cnnic.cn',
'tw' => 'whois.twnic.net.tw',
'hk' => 'whois.hkirc.hk',
'jp' => 'whois.jprs.jp',
'kr' => 'whois.kisa.or.kr',
'sg' => 'whois.sgnic.sg',
'my' => 'whois.mynic.my',
'th' => 'whois.thnic.co.th',
'vn' => 'whois.vnnic.vn',
'id' => 'whois.pandi.or.id',
'ph' => 'whois.nic.ph',
'au' => 'whois.auda.org.au',
'nz' => 'whois.srs.net.nz',
'uk' => 'whois.nic.uk',
'de' => 'whois.denic.de',
'fr' => 'whois.nic.fr',
'ru' => 'whois.tcinet.ru',
'br' => 'whois.registro.br',
'ca' => 'whois.cira.ca',
'us' => 'whois.nic.us',
'eu' => 'whois.eu',
'io' => 'whois.nic.io',
'ai' => 'whois.nic.ai',
'co' => 'whois.nic.co',
'me' => 'whois.nic.me',
'tv' => 'whois.nic.tv',
'cc' => 'whois.nic.cc',
'ws' => 'whois.worldsite.ws',
// 特殊
'edu' => 'whois.educause.edu',
'gov' => 'whois.nic.gov',
'mil' => 'whois.nic.mil',
'int' => 'whois.iana.org',
'arpa' => 'whois.iana.org',
];
if (!isset($servers[$tld])) {
// 嘗試 IANA 根伺服器查詢授權伺服器
$servers[$tld] = 'whois.iana.org';
}
$server = $servers[$tld];
// 4. 建立 TCP 連線查詢 (Whois 使用 Port 43)
$fp = @fsockopen($server, 43, $errno, $errstr, $timeout);
if (!$fp) {
throw new Exception("無法連線至 Whois 伺服器 $server: $errstr ($errno)");
}
stream_set_timeout($fp, $timeout);
fwrite($fp, $domain . "\r\n");
$response = '';
while (!feof($fp)) {
$response .= fread($fp, 8192);
}
fclose($fp);
// 5. 簡易判斷是否可註冊 (不同註冊局關鍵字不同)
$availableKeywords = [
'no match',
'not found',
'available',
'free',
'no entries',
'domain not found',
'status: available',
];
$available = false;
$lowerResp = strtolower($response);
foreach ($availableKeywords as $kw) {
if (strpos($lowerResp, $kw) !== false) {
$available = true;
break;
}
}
// 6. 簡易解析關鍵欄位 (各註冊局格式差異大,僅示範常見)
$parsed = [];
$patterns = [
'registrar' => '/Registrar:\s*(.+)/i',
'creation_date' => '/(?:Creation Date|Created On):\s*(.+)/i',
'expiry_date' => '/(?:Expir|Registry Expiry Date):\s*(.+)/i',
'name_servers' => '/Name Server:\s*(.+)/i',
'status' => '/Status:\s*(.+)/i',
];
foreach ($patterns as $key => $pattern) {
if (preg_match_all($pattern, $response, $matches)) {
$parsed[$key] = array_map('trim', $matches[1]);
}
}
return [
'domain' => $domain,
'server' => $server,
'raw' => $response,
'available' => $available,
'parsed' => $parsed,
];
}
<?php
try {
$result = whoisQuery('google.com');
echo "域名: {$result['domain']}\n";
echo "伺服器: {$result['server']}\n";
echo "可註冊: " . ($result['available'] ? '是' : '否') . "\n";
echo "註冊商: " . ($result['parsed']['registrar'][0] ?? 'N/A') . "\n";
echo "建立日期: " . ($result['parsed']['creation_date'][0] ?? 'N/A') . "\n";
echo "到期日期: " . ($result['parsed']['expiry_date'][0] ?? 'N/A') . "\n";
} catch (Exception $e) {
echo "查詢失敗: " . $e->getMessage();
}
Whois 查詢較慢 (通常 0.5~3 秒),且註冊局有頻率限制。**必須加入快取**:
<?php
function whoisQueryCached(string $domain, int $ttl = 86400): array {
$cacheKey = 'whois:' . md5(strtolower($domain));
// 假設使用 Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cached = $redis->get($cacheKey);
if ($cached !== false) {
return json_decode($cached, true);
}
$result = whoisQuery($domain);
$redis->setex($cacheKey, $ttl, json_encode($result));
return $result;
}
https://rdap.verisign.com/com/v1/domain/example.comfunction rdapQuery(string $domain): array {
$url = "https://rdap.org/domain/$domain"; // 自動導向至正確註冊局
$json = @file_get_contents($url);
return $json ? json_decode($json, true) : [];
}
co.uk, com.tw 為雙段 TLD)。whoisQuery() 提供完整的域名查詢功能,內建伺服器對照、可用性判斷、關鍵欄位解析。生產環境**必須**搭配快取、頻率控制、錯誤重試,並關注 RDAP 遷移趨勢。嚴格遵守查詢頻率限制與法律法規,避免 IP 被封禁或法律風險。