dnsmgr/app/utils/CertDnsUtils.php
2024-12-21 17:07:51 +08:00

152 lines
7.3 KiB
PHP

<?php
namespace app\utils;
use Exception;
use think\facade\Db;
use app\lib\DnsHelper;
class CertDnsUtils
{
public static function addDns($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) {
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']);
});
$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) {
return $v['Type'] == $row['type'] && $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']);
}
}
$res = $dns->addDomainRecord($row['name'], $row['type'], $row['value'], DnsHelper::$line_name[$drow['type']]['DEF'], 600);
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);
}
}
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) {
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']);
});
$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) {
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;
}
}