Private/Resolve-TLDnsRecord.ps1
|
function Resolve-TLDnsRecord { <# .SYNOPSIS Resolves TXT or CNAME records cross-platform. .DESCRIPTION Prefers Resolve-DnsName where available (Windows). Falls back to DNS-over-HTTPS (Cloudflare) on platforms without the DnsClient module, because .NET offers no TXT/CNAME lookup API. Returns an array of strings (TXT contents or CNAME targets); empty array when unresolved. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Name, [Parameter(Mandatory)] [ValidateSet('TXT', 'CNAME')] [string]$Type ) if (Get-Command -Name 'Resolve-DnsName' -ErrorAction SilentlyContinue) { try { $records = @(Resolve-DnsName -Name $Name -Type $Type -DnsOnly -ErrorAction Stop) if ($Type -eq 'TXT') { return @($records | Where-Object { $_.PSObject.Properties['Strings'] -and $_.Strings } | ForEach-Object { ($_.Strings -join '') }) } return @($records | Where-Object { [string]$_.QueryType -eq 'CNAME' } | ForEach-Object { $_.NameHost }) } catch { Write-Verbose ("DNS lookup {0} {1} returned nothing: {2}" -f $Type, $Name, $_.Exception.Message) return @() } } # Cross-platform fallback: DNS-over-HTTPS. try { $uri = 'https://cloudflare-dns.com/dns-query?name={0}&type={1}' -f [uri]::EscapeDataString($Name), $Type $response = Invoke-RestMethod -Uri $uri -Headers @{ accept = 'application/dns-json' } -ErrorAction Stop if ($response.PSObject.Properties['Answer'] -and $response.Answer) { if ($Type -eq 'TXT') { # TXT answers arrive quoted and possibly segmented: "part1" "part2" return @($response.Answer | Where-Object { $_.type -eq 16 } | ForEach-Object { ($_.data -replace '"\s*"', '').Trim('"') }) } return @($response.Answer | Where-Object { $_.type -eq 5 } | ForEach-Object { ([string]$_.data).TrimEnd('.') }) } } catch { Write-Verbose ("DoH lookup {0} {1} failed: {2}" -f $Type, $Name, $_.Exception.Message) } return @() } |