From bc35ee946961d8e8d8fbb0a9b6daa6763ed2ceae Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Wed, 18 Aug 2021 17:13:42 +0800 Subject: [PATCH] feat: dnssec field of IANA database --- src/dnssec.php | 122 +++++++++++++++++++++++++++++++++++++++++++++++++ src/iana.php | 10 +--- src/main.php | 48 +++++++++++++++++-- 3 files changed, 168 insertions(+), 12 deletions(-) create mode 100644 src/dnssec.php diff --git a/src/dnssec.php b/src/dnssec.php new file mode 100644 index 0000000..a5ac6d5 --- /dev/null +++ b/src/dnssec.php @@ -0,0 +1,122 @@ + dnssec page'); + } + $html = explode('', $html[3]); + if (count($html) !== 2) { + die('error -> dnssec page'); + } + $html = explode('' . PHP_EOL . ' dnssec list'); + } + $color = substr($match[0], -6); + preg_match('/href=http:\/\/www.iana.org\/domains\/root\/db\/[a-z0-9-]+.html>/', $row, $match); + if (count($match) !== 1) { + die('error -> dnssec list'); + } + $tld = str_replace('.html>', '', $match[0]); + $tld = '.' . str_replace('href=http://www.iana.org/domains/root/db/', '', $tld); + + $row = str_replace('YES', '|YES|', $row); + $row = str_replace('NO', '|NO|', $row); + preg_match('/\|(YES|NO)\|\|(YES|NO)\|\|(YES|NO)\|/', $row, $match); + if (count($match) !== 4) { + die('error -> dnssec list'); + } + if ($match[0] === '|YES||YES||NO|') { + $type = 1; // 正常DNSSEC + if ($color !== '00CC00') { + die('error -> dnssec list'); + } + } else if ($match[0] === '|NO||NO||NO|') { + $type = 2; // 未启用DNSSEC + if ($color !== 'F2F2F2') { + die('error -> dnssec list'); + } + } else if ($match[0] === '|YES||NO||NO|') { + $type = 3; // 启用DNSSEC 但未部署DS记录 + if ($color !== '3399CC') { + die('error -> dnssec list'); + } + } else { + die('error -> dnssec list'); + } + $dnssec[$tld] = array( + 'type' => $type + ); + } + return $dnssec; + } + + public function getDsRecord($tld) { // 获取DS记录 + $tld = substr($tld, 1, strlen($tld) - 1); // 去除前面的. + $raw = shell_exec('dig DS +short @' . chr(mt_rand(97, 109)) . '.root-servers.net ' . $tld . '.'); + if ($raw == '') { + return array(); + } + $dsRecords = explode(PHP_EOL, $raw); + foreach ($dsRecords as $dsRecord) { + if ($dsRecord == '') { continue; } + $ds = explode(' ', $dsRecord); + if (count($ds) !== 4 && count($ds) !== 5) { + return 'error'; + } + $temp['tag'] = $ds[0]; + $temp['algorithm'] = $ds[1]; + $temp['digest'] = $ds[2]; + $temp['hash'] = $ds[3]; + if (count($ds) === 5) { + $temp['hash'] .= $ds[4]; + } + $dnssec[] = $temp; + } + foreach ($dnssec as $row) { + if ($row['digest'] === '1') { // SHA-1 + preg_match('/^[0-9A-Z]{40}$/', $row['hash'], $match); + if (count($match) !== 1) { + return 'error'; + } + } else if ($row['digest'] === '2') { // SHA-256 + preg_match('/^[0-9A-Z]{64}$/', $row['hash'], $match); + if (count($match) !== 1) { + return 'error'; + } + } else { // 3 -> GOST R 34.11-94 / 4 -> SHA-384 + return 'error'; + } + } + foreach ($dnssec as &$row) { // 计算权重 + $row['weight'] = $row['tag'] * 1000 + $row['algorithm'] * 10 + $row['digest']; + } + $temp = array(); // 排序算法 + foreach ($dnssec as $val){ + $temp[] = $val['weight']; + } + sort($temp); + $temp = array_flip($temp); + $sort = array(); + foreach ($dnssec as $val) { + $temp_1 = $val['weight']; + $temp_2 = $temp[$temp_1]; + $sort[$temp_2] = $val; + } + asort($sort); + $dnssec = $sort; + foreach ($dnssec as &$record) { + unset($record['weight']); + } + return $dnssec; + } +} + +?> diff --git a/src/iana.php b/src/iana.php index 1ad9eea..30d7332 100644 --- a/src/iana.php +++ b/src/iana.php @@ -271,10 +271,7 @@ class IANA { // 获取IANA顶级域名信息 private function getHtmlManager($str) { // 提取TLD所有者信息 if ($str == '') { - return array( - 'name' => array(), - 'addr' => array() - ); + return array(); } $temp = explode('
', $str); if (count($temp) !== 2) { @@ -284,10 +281,7 @@ class IANA { // 获取IANA顶级域名信息 preg_match('/\\\u[0-9a-f]{4}/', $manager, $match); $manager = substr($manager, 3 - strlen($manager)); if ($manager === 'Not assigned') { - return array( - 'name' => array(), - 'addr' => array() - ); + return array(); } $manager = explode('
', $manager); if ($temp[1] == '') { diff --git a/src/main.php b/src/main.php index a5636be..67e7f96 100644 --- a/src/main.php +++ b/src/main.php @@ -2,6 +2,7 @@ require_once './icp.php'; require_once './iana.php'; +require_once './dnssec.php'; require_once './tld-list.php'; require_once './punycode.php'; require_once './interface.php'; @@ -20,6 +21,24 @@ $icpInfo = (new ICP)->getIcpTld($csv_content); $html_content = file_get_contents('../data/tld-list.html'); $tldList = (new TldList)->getTlds($html_content); +// Get DNSSEC Info +$html_contant = curl('http://stats.research.icann.org/dns/tld_report/'); +$dnssecObj = new DNSSEC; +$dnssecList = $dnssecObj->getDnssecStatus($html_contant); +foreach ($dnssecList as $tld => $content) { + echo $tld; + $content = $dnssecObj->getDsRecord($tld); + if ($content === 'error') { + sleep(5); // 延迟5s + $content = $dnssecObj->getDsRecord($tld); + if ($content === 'error') { + die('error -> ds query fail'); + } + } + $dnssecList[$tld]['ds'] = $content; + echo PHP_EOL; +} + // Get TLD list from IANA website $html_content = curl('https://www.iana.org/domains/root/db'); if (!$html_content) { @@ -44,6 +63,22 @@ foreach ($tlds as $index => $tld) { echo PHP_EOL; } +// Add DNSSEC field for tldInfo +foreach ($dnssecList as $tld => $dnssec) { + if (!isset($tldInfo[$tld])) { + die('error -> wrong match'); + } +} +foreach ($tldInfo as $tld => $info) { + if (isset($dnssecList[$tld])) { + $tldInfo[$tld]['active'] = 'yes'; + $tldInfo[$tld]['dnssec'] = $dnssecList[$tld]; + } else { + $tldInfo[$tld]['active'] = 'no'; + $tldInfo[$tld]['dnssec'] = array(); + } +} + // Remove the TLD which not exist in IANA foreach ($icpInfo as $index => $row) { $tld = explode('.', $index); @@ -114,6 +149,7 @@ $init_iana_sql =<<exec($init_list_sql); $db->exec($init_icp_sql); $insert_sql = 'INSERT INTO iana '; -$insert_sql .= '(tld,type,manager,admin_contact,tech_contact,nameserver,website,whois,last_updated,regist_date) '; +$insert_sql .= '(tld,type,active,manager,admin_contact,tech_contact,nameserver,website,whois,last_updated,regist_date,dnssec) '; $insert_sql .= 'VALUES ('; foreach ($tldInfo as $tld => $info) { $sql = $insert_sql . '\'' . $tld . '\','; + $sql .= '\'' . $info['type'] . '\','; + $sql .= '\'' . $info['active'] . '\','; foreach ($info as $index => $field) { - if ($index === 'manager' || $index === 'admin_contact' || $index === 'tech_contact' || $index === 'nameserver') { + if ($index === 'active' || $index === 'type') { continue; } + if ($index === 'manager' || $index === 'admin_contact' || $index === 'tech_contact' || $index === 'nameserver' || $index === 'dnssec') { $field = base64_encode(json_encode($field)); } $sql .= '\'' . $field . '\''; - if ($index !== 'regist_date') { + if ($index !== 'dnssec') { $sql .= ','; } }