<# .SYNOPSIS Sets a domain controller's own DNS client settings: partner DC(s) first, loopback last. .DESCRIPTION Connects to each domain controller over CIM, finds the adapter that carries its default route (or the one you name), and sets its IPv4 DNS server list to the partner DNS servers you supply followed by 127.0.0.1. Returns the before and after for every DC. Supports -WhatIf. .PARAMETER ComputerName The domain controller to configure. Accepts pipeline input by property name, so you can feed it a CSV. .PARAMETER PartnerDnsServer IP address(es) of other DNS-hosting DCs, ideally in the same site. These go first. .PARAMETER InterfaceAlias Adapter to change, e.g. Ethernet0. Defaults to the adapter with the default gateway. .PARAMETER NoLoopback Don't append 127.0.0.1. For DCs that don't run the DNS Server role. .PARAMETER Credential Alternate credentials for the CIM connection. .EXAMPLE .\Set-DCDnsClientServer.ps1 -ComputerName DC01 -PartnerDnsServer 10.0.1.11 -WhatIf .EXAMPLE Import-Csv .\dc-dns.csv | .\Set-DCDnsClientServer.ps1 #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, ValueFromPipelineByPropertyName)][string]$ComputerName, [Parameter(Mandatory, ValueFromPipelineByPropertyName)][string[]]$PartnerDnsServer, [Parameter(ValueFromPipelineByPropertyName)][string]$InterfaceAlias, [switch]$NoLoopback, [pscredential]$Credential ) process { # CSV input gives "10.0.1.11;10.0.2.11" as one string, so split and validate here. $partners = @($PartnerDnsServer -split '[;,\s]+' | Where-Object { $_ }) foreach ($ip in $partners) { $parsed = $null if (-not [ipaddress]::TryParse($ip, [ref]$parsed) -or $parsed.AddressFamily -ne 'InterNetwork') { Write-Error "${ComputerName}: '$ip' isn't a valid IPv4 address. Skipping this DC." return } if ($ip -like '127.*') { Write-Error "${ComputerName}: leave loopback out of -PartnerDnsServer; the script adds it last. Skipping this DC." return } } $session = $null try { $cim = @{ ComputerName = $ComputerName; ErrorAction = 'Stop' } if ($Credential) { $cim.Credential = $Credential } $session = New-CimSession @cim if ($InterfaceAlias) { $ifIndex = (Get-NetAdapter -CimSession $session -Name $InterfaceAlias -ErrorAction Stop).ifIndex } else { $route = Get-NetRoute -CimSession $session -DestinationPrefix '0.0.0.0/0' -ErrorAction Stop | Sort-Object RouteMetric | Select-Object -First 1 $ifIndex = $route.ifIndex } $adapter = Get-NetAdapter -CimSession $session -InterfaceIndex $ifIndex -ErrorAction Stop $ownIPs = @((Get-NetIPAddress -CimSession $session -InterfaceIndex $ifIndex -AddressFamily IPv4 -ErrorAction Stop).IPAddress) $before = @((Get-DnsClientServerAddress -CimSession $session -InterfaceIndex $ifIndex -AddressFamily IPv4 -ErrorAction Stop).ServerAddresses) # The DC's own address as a "partner" is just loopback in disguise, and in first place that's what we're avoiding. $self = @($partners | Where-Object { $ownIPs -contains $_ }) if ($self) { Write-Error "${ComputerName}: $($self -join ', ') is this DC's own address. Use a different DC as the partner. Skipping this DC." return } $desired = @($partners) if (-not $NoLoopback) { $desired += '127.0.0.1' } $result = [pscustomobject]@{ ComputerName = $ComputerName Adapter = $adapter.Name Before = $before -join ', ' After = $desired -join ', ' Result = '' } if (($before -join ',') -eq ($desired -join ',')) { $result.Result = 'Already correct' } elseif ($PSCmdlet.ShouldProcess("$ComputerName ($($adapter.Name))", "Set DNS servers to $($desired -join ', ')")) { Set-DnsClientServerAddress -CimSession $session -InterfaceIndex $ifIndex -ServerAddresses $desired -ErrorAction Stop $check = @((Get-DnsClientServerAddress -CimSession $session -InterfaceIndex $ifIndex -AddressFamily IPv4).ServerAddresses) $result.After = $check -join ', ' $result.Result = if (($check -join ',') -eq ($desired -join ',')) { 'Updated' } else { 'Updated, but readback differs' } } else { $result.Result = 'WhatIf' } $result } catch { [pscustomobject]@{ ComputerName = $ComputerName; Adapter = $null; Before = $null; After = $null; Result = "Failed: $($_.Exception.Message)" } } finally { if ($session) { Remove-CimSession -CimSession $session } } }