Files
docs/Scripts/Powershell/General Purpose/DNS Hierarchy Correction.md
Nicole Rappe cf6e942e4e
All checks were successful
GitOps Automatic Deployment / GitOps Automatic Deployment (push) Successful in 7s
Add Scripts/Powershell/General Purpose/DNS Hierarchy Correction.md
2025-07-16 03:24:56 -06:00

4.1 KiB

Purpose

When it comes to best-practices with Windows-based DNS servers, you never want to have 127.0.0.1 or the IP of the server itself as the primary DNS server, you want to have a different DNS server as primary, and 127.0.0.1 as the secondary or tertiary DNS server instead.

The following script will automatically detect which network interface has a default gateway (there should only ever be one default gateway on a server's networking). Then it will check if the primary DNS server is the same IP as the localhost. If it is, it checks for a secondary DNS server, if it finds one, it performs an nslookup on the secondary DNS server, and if it succeeds, it swaps the secondary DNS server as the primary, and the primary becomes the secondary (loopback).

<#
    Section: Information Gathering
    - Gather the adapter(s) with an IP, DNS servers, AND a default gateway set via WMI.
#>
$adapters = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object {
    $_.IPAddress -ne $null -and
    $_.DNSServerSearchOrder -ne $null -and
    $_.DefaultIPGateway -ne $null -and
    $_.DefaultIPGateway.Count -gt 0
}

foreach ($adapter in $adapters) {
    Write-Host "-----------------------------------------------------------"
    Write-Host "Adapter Name: $($adapter.Description)"
    Write-Host "IP Address: $($adapter.IPAddress -join ', ')"
    Write-Host "Default Gateway: $($adapter.DefaultIPGateway -join ', ')"
    Write-Host "DNS Server(s): $($adapter.DNSServerSearchOrder -join ', ')"

    $localIPs = $adapter.IPAddress + "127.0.0.1"

    <#
        Section: Information Analysis
        - Identify primary and secondary DNS.
        - Check if primary DNS matches any local IP.
    #>
    $primaryDNS = $adapter.DNSServerSearchOrder[0]
    $secondaryDNS = $null
    if ($adapter.DNSServerSearchOrder.Count -ge 2) {
        $secondaryDNS = $adapter.DNSServerSearchOrder[1]
    }

    $isPrimaryLocal = $false
    foreach ($local in $localIPs) {
        if ($primaryDNS -eq $local) {
            $isPrimaryLocal = $true
            break
        }
    }
    if ($isPrimaryLocal) {
        Write-Host "Primary DNS matches local IP: Yes"
    } else {
        Write-Host "Primary DNS matches local IP: No"
    }

    <#
        Section: Information Processing
        - If the primary DNS is a local IP and a secondary exists:
            a. Test the secondary DNS with nslookup on google.com.
            b. Only swap if nslookup is successful.
    #>
    if ($isPrimaryLocal -and $secondaryDNS) {
        Write-Host "Testing nslookup on secondary DNS ($secondaryDNS)..."
        $nslookupResult = nslookup google.com $secondaryDNS 2>&1

        # Simple check for nslookup success
        $nslookupSuccess = $false
        if ($nslookupResult -match "Name:\s*google\.com") { $nslookupSuccess = $true }
        if ($nslookupResult -match "Non-authoritative answer:") { $nslookupSuccess = $true }
        if ($nslookupResult -match "Address:") { $nslookupSuccess = $true }

        if ($nslookupSuccess) {
            Write-Host "NSlookup via secondary DNS: SUCCESS"
            # Swap
            $newDnsServers = @($secondaryDNS, $primaryDNS)
            if ($adapter.DNSServerSearchOrder.Count -gt 2) {
                $newDnsServers += $adapter.DNSServerSearchOrder[2..($adapter.DNSServerSearchOrder.Count - 1)]
            }
            $result = $adapter.SetDNSServerSearchOrder($newDnsServers)
            if ($result.ReturnValue -eq 0) {
                Write-Host "DNS servers swapped. New primary: $secondaryDNS, New secondary: $primaryDNS"
            } else {
                Write-Host "Failed to set new DNS order. Return code: $($result.ReturnValue)"
            }
        } else {
            Write-Host "NSlookup via secondary DNS: FAILED"
            Write-Host "DNS servers NOT swapped."
        }
    } elseif ($isPrimaryLocal -and -not $secondaryDNS) {
        Write-Host "No secondary DNS set. No changes made."
    } else {
        Write-Host "DNS servers are correct. No changes needed."
    }

    Write-Host "-----------------------------------------------------------"
}

Write-Host "DNS check and correction completed for adapters with a default gateway."