Site icon Think PowerShell

Change DNS Servers for Computers with Static IP Addresses

DNS Server Settings Screenshot
Update DNS servers using PowerShell.

Easily change DNS servers for computers with static IP addresses using PowerShell. Run locally or remote.

Changing DNS servers

Recently I provisioned new domain controllers as part of a migration from a 2008 R2 Active Directory forest to a 2016 Active Directory forest. Like the existing 2008 R2 domain controllers, the new domain controllers are configured as AD integrated DNS servers and will be the primary and secondary DNS servers used on the internal network.

Changing DNS servers for clients using DHCP is a trivial matter; just update Option 6 for the DHCP scope with the new name server IP addresses and restart the client (or wait until they renew their lease).

However if you are like a lot of environments, you have Windows servers and maybe even workstations configured with static IP addresses and static DNS servers. How can you systematically update these configurations?

Change DNS servers with Win32_NetworkAdapterConfiguration

We can use PowerShell and Get-WmiInstance or Get-CimInstance (Win 8/2012 or later). For compatibility, we will be demonstrating using Get-WmiInstance.

In our scenario, our old DNS servers were 192.168.1.11 and 192.168.1.12. We will be replacing these with 192.168.1.13 and 192.168.1.14. We use the following snippet leveraging the class Win32_NetworkAdapterConfiguration to return a list of all non-DHCP adapters with DNS servers configured.

$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}

To see the current DNS servers, we run the following:

PS C:\Windows\system32> $Adapters | ForEach-Object {$_.DNSServerSearchOrder}
192.168.1.11
192.168.1.12

To update the DNS servers for adapters meeting this criteria, we run the following:

$NewDnsServerSearchOrder = "192.168.1.13","192.168.1.14"

$Adapters | ForEach-Object {$_.SetDNSServerSearchOrder($NewDnsServerSearchOrder)} | Out-Null

To confirm the servers have been updated, re-run our original Get sequence:

$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}

PS C:\Windows\system32> $Adapters | ForEach-Object {$_.DNSServerSearchOrder}
192.168.1.13
192.168.1.14

Remotely updating DNS servers for set of computers

The previous section covered the basic updating of the DNS servers locally on a single computer. However you may have the need to update multiple computers remotely.

One approach would be to query your Active Directory to get a list of all computers that have statically assigned IP addresses. For example, it may be that all of your computers running a Windows Server OS have static IPs.

Get all “Windows Server” AD computers

We can get all of the the computers in Active Directory that are running a “Windows Server” build using the following Get-ADComputer query:

$Computers = Get-ADComputer -Filter '(OperatingSystem -like "Windows Server*")' | Sort-Object Name

Use Invoke-Command to update DNS on remote computers

We now have a set of computers to process. We will use Invoke-Command to connect via WinRM to the remote computer and execute the previous commands locally on the computer.

ForEach ($Computer in $Computers) {
    Write-Host "$($Computer.Name): " -ForegroundColor Yellow
    Invoke-Command -ComputerName $Computer.Name -ScriptBlock {
        $NewDnsServerSearchOrder = "192.168.1.13","192.168.1.14"
        $Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}
        
        # Show DNS servers before update
        Write-Host "Before: " -ForegroundColor Green
        $Adapters | ForEach-Object {$_.DNSServerSearchOrder}

        # Update DNS servers
        $Adapters | ForEach-Object {$_.SetDNSServerSearchOrder($NewDnsServerSearchOrder)} | Out-Null

        # Show DNS servers after update
        $Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}
        Write-Host "After: " -ForegroundColor Green
        $Adapters | ForEach-Object {$_.DNSServerSearchOrder}
    }
}

Why we used Invoke-Command

We could use the WMI cmdlets directly against the remote computer, but it would require all of the necessary network port access and permissions for using WMI remotely. Connecting using WinRM only requires a single network port to be opened and lets us run all other cmdlets without having to give a lot of thought to remote security and performance over the network.

Set-DnsClientServerAddress: Windows 8/2012 or newer

The method described above is intended for maximum compatibility: it will work with Windows Server 2003 all the way through Windows Server 2016. If however your environment is running Windows 8 / Windows Server 2012  and above, you do not need to use the WMI cmdlets, you can use the newer cmdlet Set-DnsClientServerAddress.

Set-DnsClientServerAddress -InterfaceIndex 2 -ServerAddresses ("192.168.1.13","192.168.1.14")

Note that we specified the InterfaceIndex. Other interface identification options are InterfaceAlias or you can pass a CimInstance for an interface to the cmdlet. You could use this cmdlet in hybrid with our previous Get-WmiObject query:

$Adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DHCPEnabled -ne 'True' -and $_.DNSServerSearchOrder -ne $null}

$Adapters | Set-DnsClientServerAddress -ServerAddresses "192.168.1.13","192.168.1.14"

Conclusion

Using this approach as a starting point, you can modify as required fit your own environment’s requirements to confidently and efficiently update DNS servers for computers with statically assigned IPs.

Exit mobile version