With the new infrastructure for DHCP policies available in Windows Server 2012, one can enable or restrict access to clients based on their MAC-Address (Link layer filtering) even at the scope level. This is the link which explains more about this topic.

Since there could be a large number of MAC-addresses that need to be added to such a list, doing this operation via UI might be a bit cumbersome. Here is a small script that takes as input: a file which contains the list of MAC-addresses (line separated), the scope ID, and whether this list is meant to be used as an allow list or deny list. This script will enable creation of a DHCP policy to configure an allow list or a deny list on a scope for MAC-address based filtering.

A sample input file format could look like this-

aabbccddeeff
112233*
abcdef123456
0a-32-b3-4e*

Such a file would be parsed using this powershell script and all these MAC-addresses could be added to an allow or deny list for a DHCP scope.

 

Usage: .\ScopeLevelMacFiltering.ps1 [-ScopeId] <ipaddress> [-InputFileName] <string> [[-IsAllow] <bool>] [<CommonParameters>]

ScopeId: A scope id within which the allow or deny list is to be configured.
InputFileName: Name of a text file which contains a list of line separated MAC-addresses that need to be entered into the allow/deny list.
IsAllow: True if one needs to configure an Allow List and False if Deny List. By default, this field is true.

Example usage: .\ScopeLevelMacFiltering.ps1 -ScopeId 10.0.0.0 -InputFileName .\MACDenyList.txt -IsAllow $false

The target DHCP Server can be Windows Server 2012 and above.

Expectations:

PowerShell
Edit|Remove
################################################## 
# 
# ScopeLevelMacFiltering.ps1 
# Scope-level Link layer filtering using DHCP policies in Windows Server 2012. 
# This script enables creation of an allow list or a deny list (from an input file) of MAC addresses for a specified DHCP scope. 
# 
################################################## 
 
param( 
    [parameter(Mandatory=$true)] 
    [ipaddress] 
    $ScopeId, 
     
    [parameter(Mandatory=$true)] 
    [string]  
    $InputFileName, 
     
    #Default is true. Creates an allow-list by default 
    [parameter(Mandatory=$false)] 
    [bool]  
    $IsAllow = $true 
) 
 
 
$filename = $InputFileName 
$allow = $IsAllow 
 
# Attempt to read the contents of the input file. Spew out any failure here. 
try 
{ 
    $filecontent = Get-Content $filename -ErrorAction Stop 
} 
catch 
{ 
    throw 
} 
 
$operator = "" 
$condition = "" 
$policyname = "MAC-based policy: " 
$description = "" 
$descr1 = "The MAC addresses in this policy will" 
$descr2 = "be leased IP addresses" 
$maclist = @() 
 
# Populate the policy name, description, condition for the policy. 
if($allow -eq $true) 
{ 
    $operator = "EQ" 
    $condition = "OR" 
    $policyname = $policyname + "Allow list" 
    $description = $descr1 + " " + $descr2 
} 
elseif ($allow -eq $false) 
{ 
    $operator = "NE" 
    $condition = "AND" 
    $policyname = $policyname + "Deny list" 
    $description = $descr1 + " not " + $descr2 
} 
 
# Attempt to read the entire list of MAC-addresses into an array. 
# Finally, The array $maclist would look like the following for an allow list - 
# @("EQ", "mac-address1", "EQ", "mac-address2", "EQ", "mac-address3" ..) 
foreach ($mac in $filecontent) 
{ 
    $maclist +$operator 
    if($mac -ne "") 
    { 
        $maclist +$mac 
     } 
} 
 
try 
{ 
    Add-DhcpServerv4Policy -Name $policyname -Description $description -ScopeId $ScopeId -Condition $condition -MacAddress $maclist -ErrorAction Stop 
} 
catch 
{ 
    # Creation of a policy could fail due to a number of reasons - 
    # 1. The target DHCP server is not running. 
    # 2. The specified scope id doesn't exist. 
    # 3. Another policy with the same name exists on the specified scope. 
    # 4. The input file was not formatted correctly with MAC addresses. 
    # Spew the output on the screen, and don't continue further. 
 
    throw 
} 
  
try 
{ 
    # Fetch the start and end address of this scope to set that to the start and end range for this policy. 
    # The intent being to create a policy with range as the entire address range of the scope. 
 
    $scope = Get-DhcpServerv4Scope $ScopeId -ErrorAction Stop 
    $start = [ipaddress]$scope.StartRange 
    $end = [ipaddress]$scope.EndRange 
 
    Add-DhcpServerv4PolicyIPRange -Name $policyname -ScopeId $ScopeId -StartRange $start -EndRange $end -ErrorAction Stop 
} 
catch 
{ 
    # If the creation of policy succeeded but the addition of range failed, it is most likely due to existence of another 
    # range-based policy in the same scope. Whatever the reason, attempt to rollback by deleting the created policy. 
 
    Remove-DhcpServerv4Policy -Name $policyname -ScopeId $ScopeId 
    throw 
} 
 
Write-Host "The script executed successfully and the required policy was created on scope" $ScopeId.ToString() 
Write-Host "" 
 
Exit