$list) { $drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', $mainDomain)->field('A.*,B.type')->find(); if (!$drow && preg_match('/^xn--/', $mainDomain)) { $drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', idn_to_utf8($mainDomain))->field('A.*,B.type')->find(); } if (!$drow) { if ($cname) { foreach ($list as $key => $row) { if ($row['name'] == '_acme-challenge') { $domain = $mainDomain; } else { $domain = str_replace('_acme-challenge.', '', $row['name']) . '.' . $mainDomain; } $cname_row = Db::name('cert_cname')->alias('A')->join('domain B', 'A.did = B.id')->where('A.domain', $domain)->field('A.*,B.name cnamedomain')->find(); if ($cname_row) { $row['name'] = $cname_row['rr']; $cnameDomainList[$cname_row['cnamedomain']][] = $row; unset($list[$key]); } else { throw new Exception('域名'.$domain.'未在本系统添加'); } } } else { throw new Exception('域名'.$mainDomain.'未在本系统添加'); } } if (empty($list)) continue; $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); usort($list, function ($a, $b) { return strcmp($a['name'], $b['name']); }); if ($drow['type'] == 'huawei') { $list = self::getHuaweiDnsRecords($list); } $records = []; foreach ($list as $row) { $domain = $row['name'] . '.' . $mainDomain; if (!isset($records[$row['name']])) $records[$row['name']] = $dns->getSubDomainRecords($row['name'], 1, 100); if (!$records[$row['name']]) throw new Exception('获取'.$domain.'记录列表失败,'.$dns->getError()); $filter_records = array_filter($records[$row['name']]['list'], function ($v) use ($row) { if (is_array($v['Value'])) $v['Value'] = implode(',', $v['Value']); return $v['Type'] == $row['type'] && ($v['Value'] == $row['value'] || rtrim($v['Value'], '.') == $row['value']); }); if (!empty($filter_records)) { foreach ($filter_records as $recordid => $record) { unset($records[$row['name']]['list'][$recordid]); } continue; } $filter_records = array_filter($records[$row['name']]['list'], function ($v) use ($row) { return $v['Type'] == $row['type']; }); if (!empty($filter_records)) { foreach ($filter_records as $recordid => $record) { $dns->deleteDomainRecord($record['RecordId']); unset($records[$row['name']]['list'][$recordid]); $log('Delete DNS Record: '.$domain.' '.$row['type']); } } $ttl = $drow['type'] == 'namesilo' ? 3600 : 600; $res = $dns->addDomainRecord($row['name'], $row['type'], $row['value'], DnsHelper::$line_name[$drow['type']]['DEF'], $ttl); if (!$res && $row['type'] != 'CAA') throw new Exception('添加'.$domain.'解析记录失败,' . $dns->getError()); $log('Add DNS Record: '.$domain.' '.$row['type'].' '.$row['value']); } } if (!empty($cnameDomainList)) { self::addDns($cnameDomainList, $log); } } private static function getHuaweiDnsRecords($list) { //将name相同的TXT记录合并 $txt_records = []; foreach ($list as $key => $row) { if ($row['type'] == 'TXT') { $txt_records[$row['name']][] = $row['value']; unset($list[$key]); } } foreach ($txt_records as $name => $rows) { $list[] = ['name' => $name, 'type' => 'TXT', 'value' => '"' . implode('","', $rows) . '"']; } return $list; } public static function delDns($dnsList, callable $log, $cname = false) { $cnameDomainList = []; foreach ($dnsList as $mainDomain => $list) { $drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', $mainDomain)->field('A.*,B.type')->find(); if (!$drow && preg_match('/^xn--/', $mainDomain)) { $drow = Db::name('domain')->alias('A')->join('account B', 'A.aid = B.id')->where('A.name', idn_to_utf8($mainDomain))->field('A.*,B.type')->find(); } if (!$drow) { if ($cname) { foreach ($list as $key => $row) { if ($row['name'] == '_acme-challenge') { $domain = $mainDomain; } else { $domain = str_replace('_acme-challenge.', '', $row['name']) . '.' . $mainDomain; } $cname_row = Db::name('cert_cname')->alias('A')->join('domain B', 'A.did = B.id')->where('A.domain', $domain)->field('A.*,B.name cnamedomain')->find(); if ($cname_row) { $row['name'] = $cname_row['rr']; $cnameDomainList[$cname_row['cnamedomain']][] = $row; unset($list[$key]); } else { throw new Exception('域名'.$domain.'未在本系统添加'); } } } else { throw new Exception('域名'.$mainDomain.'未在本系统添加'); } } if (empty($list)) continue; $dns = DnsHelper::getModel($drow['aid'], $drow['name'], $drow['thirdid']); usort($list, function ($a, $b) { return strcmp($a['name'], $b['name']); }); if ($drow['type'] == 'huawei') { $list = self::getHuaweiDnsRecords($list); } $records = []; foreach ($list as $row) { //if ($row['type'] == 'CAA') continue; $domain = $row['name'] . '.' . $mainDomain; if (!isset($records[$row['name']])) $records[$row['name']] = $dns->getSubDomainRecords($row['name'], 1, 100); if (!$records[$row['name']]) throw new Exception('获取'.$domain.'记录列表失败,'.$dns->getError()); $filter_records = array_filter($records[$row['name']]['list'], function ($v) use ($row) { if (is_array($v['Value'])) $v['Value'] = implode(',', $v['Value']); return $v['Type'] == $row['type'] && ($v['Value'] == $row['value'] || rtrim($v['Value'], '.') == $row['value']); }); if (empty($filter_records)) continue; foreach ($filter_records as $record) { $dns->deleteDomainRecord($record['RecordId']); $log('Delete DNS Record: '.$domain.' '.$row['type'].' '.$row['value']); } } } if (!empty($cnameDomainList)) { self::delDns($cnameDomainList, $log); } } public static function verifyDns($dnsList) { if (empty($dnsList)) return true; foreach ($dnsList as $mainDomain => $list) { foreach ($list as $row) { if ($row['type'] == 'CAA') continue; $domain = $row['name'] . '.' . $mainDomain; $result = DnsQueryUtils::get_dns_records($domain, $row['type']); if (!$result || !in_array($row['value'], $result) && !in_array(strtolower($row['value']), $result)) { $result = DnsQueryUtils::query_dns_doh($domain, $row['type']); if (!$result || !in_array($row['value'], $result) && !in_array(strtolower($row['value']), $result)) { return false; } } } } return true; } }