Skip to content

P03-T04 - Sites and Subnets

Objective

Rename the default AD site to HQ, map every documented internal VLAN subnet to it, and prove site discovery from both HQ-DC01 and a real VLAN 30 client.

Validated in the lab on Saturday, July 18, 2026, using QEMU Guest Agent only as execution transport. The production sysadmin runs the PowerShell directly on HQ-DC01.

Inputs

Key Validated value Configurable parameter
Site HQ SiteName
Location Headquarters Location
Subnets VLANs 10 through 110 in the authoritative plan Subnets

Target State

Property Required result
AD site HQ
DC server object CN=HQ-DC01,CN=Servers,CN=HQ,...
Subnet objects All 11 documented internal /24 networks mapped to HQ
DC site discovery HQ
VLAN 30 client discovery HQ

Prechecks

  • Complete P03-T01, P03-T02, and P03-T03.
  • Confirm dcdiag Advertising, Services, SYSVOL, and NetLogons tests pass.
  • Compare the requested subnet list with Addressing and VLANs; stop if the customer addressing differs.
  • Do not include WAN transit or RouterOS-only container networks as AD client subnets.

Current State Verification

Run from elevated PowerShell on HQ-DC01:

Import-Module ActiveDirectory
Get-ADReplicationSite -Filter *
Get-ADReplicationSubnet -Filter * | Sort-Object Name
nltest /dsgetsite

The validated lab initially contained only Default-First-Site-Name and no subnet objects.

Execution

Copy the complete script below to HQ-DC01 or save it as Configure-HQ-ADSites.ps1:

Show full Sites and Subnets script
[CmdletBinding()]
param(
    [ValidatePattern('^[A-Za-z0-9][A-Za-z0-9 _-]{0,63}$')]
    [string]$SiteName = 'HQ',
    [string]$Location = 'Headquarters',
    [string[]]$Subnets = @(
        '172.20.10.0/24',
        '172.20.20.0/24',
        '172.20.30.0/24',
        '172.20.40.0/24',
        '172.20.50.0/24',
        '172.20.60.0/24',
        '172.20.70.0/24',
        '172.20.80.0/24',
        '172.20.90.0/24',
        '172.20.100.0/24',
        '172.20.110.0/24'
    ),
    [switch]$ValidateOnly
)

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'

function Assert-Elevated {
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($identity)
    if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
        throw 'Run this script from an elevated PowerShell session.'
    }
}

function Get-SiteState {
    Write-Output '=== Sites ==='
    Get-ADReplicationSite -Filter * | Sort-Object Name | ForEach-Object {
        Write-Output "Site: $($_.Name) / DN=$($_.DistinguishedName)"
    }
    Write-Output '=== Subnets ==='
    Get-ADReplicationSubnet -Filter * | Sort-Object Name | ForEach-Object {
        Write-Output "Subnet: $($_.Name) / Site=$($_.Site) / Location=$($_.Location)"
    }
    Write-Output '=== Local Site Discovery ==='
    nltest /dsgetsite
}

Assert-Elevated
Import-Module ActiveDirectory

$domain = Get-ADDomain
$configDn = "CN=Configuration,$($domain.DistinguishedName)"
$defaultSiteDn = "CN=Default-First-Site-Name,CN=Sites,$configDn"

Get-SiteState
if ($ValidateOnly) {
    Write-Output 'Validation mode only. No site or subnet configuration was changed.'
    return
}

$site = Get-ADReplicationSite -Filter "Name -eq '$SiteName'" -ErrorAction SilentlyContinue
if (-not $site) {
    if (Get-ADObject -Identity $defaultSiteDn -ErrorAction SilentlyContinue) {
        Rename-ADObject -Identity $defaultSiteDn -NewName $SiteName
    }
    else {
        New-ADReplicationSite -Name $SiteName -Description 'Primary headquarters site' | Out-Null
    }
}

foreach ($subnetName in $Subnets) {
    $subnet = Get-ADReplicationSubnet -Filter "Name -eq '$subnetName'" -ErrorAction SilentlyContinue
    if ($subnet) {
        Set-ADReplicationSubnet -Identity $subnet.DistinguishedName -Site $SiteName -Location $Location
    }
    else {
        New-ADReplicationSubnet -Name $subnetName -Site $SiteName -Location $Location | Out-Null
    }
}

Write-Output '=== Result ==='
Get-SiteState

$serverSearchBase = "CN=Servers,CN=$SiteName,CN=Sites,$configDn"
$server = Get-ADObject -LDAPFilter "(cn=$env:COMPUTERNAME)" -SearchBase $serverSearchBase -ErrorAction SilentlyContinue
if (-not $server) { throw "The server object for '$env:COMPUTERNAME' was not found beneath site '$SiteName'." }

Preview the current state without changing AD:

.\Configure-HQ-ADSites.ps1 -ValidateOnly

Apply the validated site and subnet baseline:

.\Configure-HQ-ADSites.ps1

The default subnet array contains:

172.20.10.0/24   172.20.20.0/24   172.20.30.0/24
172.20.40.0/24   172.20.50.0/24   172.20.60.0/24
172.20.70.0/24   172.20.80.0/24   172.20.90.0/24
172.20.100.0/24  172.20.110.0/24

Validation

On HQ-DC01:

Get-ADReplicationSite -Filter * | Select-Object Name,DistinguishedName
Get-ADReplicationSubnet -Filter * | Sort-Object Name | Select-Object Name,Site,Location
Get-ADObject -LDAPFilter '(cn=HQ-DC01)' -SearchBase 'CN=Servers,CN=HQ,CN=Sites,CN=Configuration,DC=corp,DC=gntech,DC=me'
nltest /dsgetsite
dcdiag /test:Advertising /test:Services /test:SysVolCheck /test:NetLogons

On a real domain-joined VLAN 30 workstation:

nltest /dsgetdc:corp.gntech.me /force
nltest /dsgetsite
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters' -Name DynamicSiteName

If nltest /dsgetdc reports Our Site Name: HQ but nltest /dsgetsite still returns the old name, refresh the client Netlogon cache and validate again:

Restart-Service Netlogon -Force
Start-Sleep -Seconds 3
nltest /dsgetdc:corp.gntech.me /force
nltest /dsgetsite

Validated result from HQ-CL01 at 172.20.30.101: DC site HQ, client site HQ, and DynamicSiteName=HQ.

Evidence

  • AD site and 11 subnet objects
  • HQ-DC01 server object under CN=HQ
  • passing dcdiag after the rename
  • DC nltest /dsgetsite = HQ
  • VLAN 30 client DC Locator output and DynamicSiteName=HQ

Rollback

  • Correct an incorrect subnet mapping with Set-ADReplicationSubnet.
  • Do not delete a site containing a DC server object.
  • Renaming the site back is possible but is not the preferred correction; repair the intended site design and revalidate DC Locator.