自建DNS獲取域名解析與證書告警
公司A擁有一套云上DNS服務,主要用于支持云中應用和服務的域名解析。為了滿足線下門店之間的服務互聯需求,公司在內網自建一套Windows DNS服務器,以實現門店之間的高效域名解析。此方案旨在保證內部網絡的穩定性與安全性,同時與云上DNS服務進行有效集成,需要監控證書有效性和域名解析的記錄查詢。
目 標
- 自建DNS服務:在不登錄window dns服務器的情況下,通過日志系統進行查詢解析記錄。
- HTTPS安全通信:為所有域名服務打印域名證書的時間信息。
- 告警系統:監控域名證書狀態,并在出現問題時及時告警。
業務流程
域名解析測試
- 在內部網絡的客戶端上測試域名解析,確保所有服務都能正確解析。
- 驗證HTTPS證書連接,確保瀏覽器或客戶端能夠安全訪問服務。
證書和域名監控
- 監控證書的有效期,設置告警閾值(如到期前60天)。
- 監控HTTPS服務的可用性,確保服務在DNS解析和證書有效的情況下正常運行。
告警機制
- 如果證書即將到期或已過期,發出告警,確保運維人員能夠及時更新證書。
- 實現自動化腳本,當證書即將到期時,生產新的證書進替換
服務器安裝openssl服務
- openssl軟件下載地址https://slproweb.com/download/Win64OpenSSL-3_3_2.msi。
- 軟件下載后直接點擊下一步進行安裝,直到安裝完成。
- openssl環境變量配置。
使用命令查詢openssl -version版本信息。
腳本查詢域名的A記錄、CNAME記錄、域名證書信息
手動查詢自建window dns的A記錄和CNAME記錄命令信息。
Get-DnsServerResourceRecord -ZoneName "text" | Where-Object { $_.RecordType -eq "CNAME" -or $_.RecordType -eq "A"} | Format-Table -AutoSize
在powershell上查詢單個域名的證書信息。
$domain = "text"
cmd /c "echo | openssl s_client -servername `"$($domain)`" -connect `"$($domain):443`" 2>&1 | openssl x509 -noout -dates | findstr /C:notAfter"
通過powershell腳本獲取域名詳細信息。
$zoneName = "text"
# domaininput.txt需要排除的域名列表信息
$inputFilePath = "D:\domain\domaininput.txt"
# domainoutput.txt需要輸出日志記錄的域名列表信息
$outputFilePath = "D:\domain\domainoutput.txt"
# 飛書webhook
$feishuWebhookUrl = "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxxxxxx" # 替換為你的飛書 Webhook URL
function Send-FeishuNotification {
param (
[string]$message,
[string]$color
)
if ($color -eq "blue") {
$formattedMessage = "*Success:* $message"
} elseif ($color -eq "black") {
$formattedMessage = "*Error:* $message"
} else {
$formattedMessage = $message
}
$payload = @{
msg_type = "text"
content = @{
text = $formattedMessage
}
}
$jsonPayload = $payload | ConvertTo-Json -Depth 1
Invoke-RestMethod -Uri $feishuWebhookUrl -Method Post -Body $jsonPayload -ContentType 'application/json'
}
function Get-CertificateEndDate {
param (
[string]$domain
)
Write-Host "正在處理域名: $domain"
try {
# 獲取證書到期信息
$certInfo = cmd /c "echo | openssl s_client -servername `"$($domain)`" -connect `"$($domain):443`" 2>&1 | openssl x509 -noout -dates | findstr /C:notAfter"
Write-Host "獲取的證書信息: $certInfo"
if ($certInfo -match "notAfter=(.*)") {
$formattedDate = $matches[1].Trim() # 獲取到期時間并去掉空格
Write-Host "證書到期時間: $formattedDate"
# 修剪多余空格
$formattedDate = $formattedDate -replace '\s+', ' '
# 解析日期時,指定格式并轉換為 yyyy-MM-dd
$parsedDate = [datetime]::ParseExact($formattedDate, "MMM d HH:mm:ss yyyy 'GMT'", [System.Globalization.CultureInfo]::InvariantCulture)
$endDate = $parsedDate.ToString("yyyy-MM-dd")
Write-Host "格式化后的日期: $endDate"
return $endDate
} else {
Write-Host "未找到證書信息: $certInfo"
return "2008-08-08" # 默認日期
}
} catch {
Write-Host "發生錯誤: $_"
return "2008-08-08" # 默認日期
}
}
try {
if (-Not (Test-Path $inputFilePath)) {
$errorMessage = "輸入文件不存在:$inputFilePath"
$failureMessage = "failed $zoneName $errorMessage"
Send-FeishuNotification -message $failureMessage -color "black"
exit
}
$excludedDomains = Get-Content -Path $inputFilePath | Where-Object { $_.Trim() -ne "" }
$dnsRecords = Get-DnsServerResourceRecord -ZoneName $zoneName |
Where-Object { $_.RecordType -eq "CNAME" -or $_.RecordType -eq "A" }
$output = @{}
$ignoredDomains = @()
foreach ($record in $dnsRecords) {
$hostName = $record.HostName
if ($hostName.EndsWith($zoneName, [System.StringComparison]::OrdinalIgnoreCase)) {
$fullDomain = $hostName
} else {
$fullDomain = "$hostName.$zoneName"
}
# 修正重復的域名問題
$fullDomain = $fullDomain -replace '\.text\.text\.cn$', '.text.cn'
if ($excludedDomains -notcontains $fullDomain) {
$endDate = Get-CertificateEndDate -domain $fullDomain
$key = "$fullDomain|$($record.RecordType)"
if (-not $output.ContainsKey($key)) {
$output[$key] = @{
RecordType = $record.RecordType
domain = $fullDomain
EndDate = $endDate
CimInstanceProperties = $record.RecordData
}
}
} else {
$ignoredDomains += $fullDomain
}
}
$outputArray = $output.Values
$outputLines = $outputArray | ForEach-Object {
$_ | ConvertTo-Json -Depth 1 -Compress
}
$outputLines | Set-Content -Path $outputFilePath -Encoding utf8
$lineCount = $outputLines.Count
$uniqueIgnoredDomains = $ignoredDomains | Select-Object -Unique
$ignoredJson = @{}
foreach ($domain in $uniqueIgnoredDomains) {
$ignoredJson["domain_$($ignoredJson.Count + 1)"] = $domain
}
$ignoredJsonString = $ignoredJson | ConvertTo-Json -Depth 10
$successMessage = "domain:$zoneName path:$outputFilePath row:$lineCount ignore: `n$ignoredJsonString"
Send-FeishuNotification -message $successMessage -color "blue"
} catch {
$errorMessage = $_.Exception.Message
$failureMessage = "failed $zoneName $errorMessage"
Send-FeishuNotification -message $failureMessage -color "black"
throw
}
#domainoutput.txt文件內容輸出JSON LOG信息
{"CimInstanceProperties":{"CimClass":"root/Microsoft/Windows/DNS:DnsServerResourceRecordA","CimInstanceProperties":"IPv4Address = \"20.20.20.20\"","CimSystemProperties":"Microsoft.Management.Infrastructure.CimSystemProperties"},"RecordType":"A","domain":"view.lu.cn","EndDate":"2008-08-08"}
{"CimInstanceProperties":{"CimClass":"root/Microsoft/Windows/DNS:DnsServerResourceRecordCName","CimInstanceProperties\"":"HostNameAlias = \"alb-cs.cn","CimSystemProperties":"Microsoft.Management.Infrastructure.CimSystemProperties"},"RecordType":"CNAME","domain":"pa.lu.cn","EndDate":"2025-05-31"}
使用json-hand插件進行格式化輸出展示:
飛書輸出信息提示,成功的域名地址、路徑、域名多少數量、排除的域名是那幾個。
互配置日志接入與查詢SQL
配置阿里云sls接入window dns單層json日志信息。
window dns文件的路徑地址為D:\domain\domainoutput.txt
通過sls查詢sql輸出window dns日志信息。
* | SELECT "content.domain", "content.RecordType", "content.CimInstanceProperties.CimInstanceProperties" , "content.EndDate" from log LIMIT 1000
配置告警輸出
根據查詢的sls sql語句進行針對性的配置告警和行動策略通知聚道(釘釘、短信、電話等等)。
在本文中,我們詳細探討了如何通過自建DNS實現域名解析與證書告警的管理。通過創建Purview門戶、配置密鑰保管庫、實施流量回放和監控,我們不僅提高了資產的可見性,還確保了數據的安全性和合規性。隨著企業數字化轉型的不斷深入,資產梳理和安全運營將變得愈發重要。我們鼓勵大家定期進行資產審查和監控,以應對不斷變化的安全威脅和業務需求。感謝您對安全運營工作的關注與支持,讓我們共同努力,提升企業的安全防護水平,確保業務的持續穩定運行。