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, andP03-T03. - Confirm
dcdiagAdvertising, 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:
Apply the validated site and subnet baseline:
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-DC01server object underCN=HQ- passing
dcdiagafter 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.