Windows Server 2012 R2 DHCP Failover services do not synchronise MAC Address Filters between partner servers

System Requirements:

  • Windows Server 2012 R2
  • Windows DHCP Server

The Problem:

If you are making use of the new failover features integrated into the Windows DHCP Server service in Windows Server 2012, should you also be using either positive or negative MAC address filtering for client leases, you may have already noticed (or may be surprised to discover) that the DHCP Filters table is not replicated as part of the failover configuration.

Barred clients will continue to be addressed from the peer server and after replication the Filters sections of the DHCP console on the secondary server will remain frustratingly empty.

More Info

The Microsoft DHCP Server team have this to say on the subject

“DHCP failover does not provide for replication of server level/wide configuration. Allow/Deny MAC filter is a server level/wide configuration. The reason this is not provided for is because a DHCP serve can participate in more than one failover relationships with different partner DHCP servers. In such scenarios, replicating server level configuration can lead to undesirable resultant server level/wide configuration. If your server has a single failover relationship or a allow/deny MAC address filter list that applies to all servers, you can setup a regular sync between the DHCP servers by writing a simple PowerShell script and integrating it with Windows Task Scheduler so that it runs on a periodic basis.”
teamdhcp (Technet, 2013)

In other words, you may be using filtering to dictate onto which DHCP server your clients will be forced to land. In which case you would not want the filters list to be replicated. For users who are simply using the filtering as a way to reduce the risk of rogue hosts, you would want the opposite behaviour.

Additionally, as replicate is per-scope, under the current replication model, your filter list would have to be duplicated for n scopes in order to work in a multi-scope environment. To that end, I can see Microsoft’s point, however the missed opportunity of a configurable option for how the system administrator wants to manage server setting replication would have made the Redmond DHCP team veritable princes.

The Fix

So, yes, Microsoft’s reply suggests that we can use PowerShell to do this (be it less ideal) and yes we can.

This simplified script is designed to be run on the secondary (slave) server. It does not perform a synchronisation, instead it clears its own database and then copies the database of the partner (master) server.

# PowerShell DHCP Filter Replication Script 1.0.0
# (c) C:Amie 2014
# http://www.c-amie.co.uk/$MasterServerHostname = "MyServerHostname";# Get the LOCAL filters from localhost
$lfilters = Get-DhcpServerv4Filter

# Get the REMOTE filters from $MasterServerHostname
$rfilters = invoke-command -computername $MasterServerHostname { Get-DhcpServerv4Filter }

# Delete the local Filter Set
ForEach ($filter in $rfilters) {
Remove-DhcpServerv4Filter -MacAddress $filter.MacAddress
}

# Import the new Filter Set
ForEach ($filter in $rfilters) {
write-host $filter.List
write-host $filter.MacAddress;
write-host $filter.Description
Add-DhcpServerv4Filter -List $filter.List -MacAddress $filter.MacAddress -Description $filter.Description
}

You will need to setup remote PowerShell access using Set-Item TrustedHosts <Hostname> / WinRm in order to allow remote connectivity between your server peers.

You must also remember that as the above does not perform a synchronisation, if you make filter changes on a secondary (slave) server, they will be lost at the next execution.

Finally, schedule the script to run as required through task scheduler using the following as the Program/script name in the Basic Task setup

powershell -file "x:\path\Script.ps1"

Hardening Steps

While this works, it is simplistic at best and presents a couple of problems.

Firstly, you should be mindful that the script will create a very small window of opportunity in which the server will potentially be in a filterless state. During this time, it may be able to respond to a DORA request from a unwanted node. If this is the case, you should disable any Scopes on the server, perform the filter sync and then re-enable the scope. If you wanted to do that the necessary script modification would be

# PowerShell DHCP Filter Replication Script 1.0.1
# (c) C:Amie 2014
# http://www.c-amie.co.uk/$MasterServerHostname = "MyServerHostname";
$ScopeId = 192.168.1.0;# Stop the DHCP Scope on the LOCAL server from leasing
Set-DhcpServerv4Scope -ScopeId $ScopeId -State "Inactive"

# Get the LOCAL filters from localhost
$lfilters = Get-DhcpServerv4Filter

# Get the REMOTE filters from $MasterServerHostname
$rfilters = invoke-command -computername $MasterServerHostname { Get-DhcpServerv4Filter }

# Delete the local Filter Set
ForEach ($filter in $rfilters) {
Remove-DhcpServerv4Filter -MacAddress $filter.MacAddress
}

# Import the new Filter Set
ForEach ($filter in $rfilters) {
write-host $filter.List
write-host $filter.MacAddress;
write-host $filter.Description
Add-DhcpServerv4Filter -List $filter.List -MacAddress $filter.MacAddress -Description $filter.Description
}

# Start the DHCP Scope on the LOCAL server
Set-DhcpServerv4Scope -ScopeId $ScopeId -State "Active"

The second problem is that the script itself executes in a linear fashion. It assumes that the partner server is always going to be on-line and available for processing. The problem here is that if the server is offline or isn’t able to service the sync request, it will have deleted the local filters list before the process of connecting to the peer server fails. At which point the server will void ofany filtering what so ever.

This can be hardened by introducing two credibility checks as follows:

# PowerShell DHCP Filter Replication Script 1.0.2
# (c) C:Amie 2014
# http://www.c-amie.co.uk/$MasterServerHostname = "MyServerHostname";
$ScopeId = 192.168.1.0;if (Test-Connection $MasterServerHostname -quiet) {

# Get the LOCAL filters from localhost
$lfilters = Get-DhcpServerv4Filter

# Get the REMOTE filters from $MasterServerHostname
$rfilters = invoke-command -computername $MasterServerHostname { Get-DhcpServerv4Filter }

if ($rfilters) {

# Stop the DHCP Scope on the LOCAL server from leasing
Set-DhcpServerv4Scope -ScopeId $ScopeId -State "Inactive"

# Delete the local Filter Set
ForEach ($filter in $rfilters) {
Remove-DhcpServerv4Filter -MacAddress $filter.MacAddress
}

# Import the new Filter Set
ForEach ($filter in $rfilters) {
write-host $filter.List
write-host $filter.MacAddress;
write-host $filter.Description
Add-DhcpServerv4Filter -List $filter.List -MacAddress $filter.MacAddress -Description $filter.Description
}

}

# Start the DHCP Scope on the LOCAL server
Set-DhcpServerv4Scope -ScopeId $ScopeId -State "Active"

}

In this version we perform a ping test on the Master Server (ICMP firewall settings required for success) and we check to see whether the $rFilters variable is set before deleting the contents of the local filters database. Finally, regardless of what happens, the resultant state of the server scope should remain active.