DNS Backups in PowerShell
DNS backups are a bit complicated, you need to backup and restore each zone individually with files that are in a static location in System32. Most sources I found used dnscmd
which is too DOS for me, we need to PowerShell it up. I ended up finding that Add-DnsServerPrimaryZone would work for my needs despite what some sources said about there being no PowerShell way to do this.
Code
Backup
$log = 'C:\dns_backup.log'
Start-Transcript $log
#Requires -RunAsAdministrator
# --- Initializations --- #
If (Test-Path '.\send-mail\send-mail.ps1') {
. .\send-mail\send-mail.ps1
} Else {
Throw "send-mail is missing"
}
# --- Declarations --- #
#user vars, change these
$backupLocation = "\\dsk7\backups-smb\dns\"
$archive = "C:\$(Get-Date -UFormat %Y-%m-%d)-$env:COMPUTERNAME.dns.zip"
#system vars, you likely don't change these
$dnsRoot = 'C:\Windows\System32\dns\'
$primarys = Get-DnsServerZone | Where-Object { $_.ZoneType -eq 'Primary' }
# use an array to catch bad things and put it in our email
$failureArray = @()
$result = "success"
# --- Functions --- #
Function mail {
# stop must be here so that the file can be unlocked whenever we want to mail
Stop-Transcript
If ($failureArray.Count -gt 0) {
$result = 'failure'
} Else {
$result = 'success'
}
send-mail -to 'user@contoso.com' -subject "DNS Backup on $env:COMPUTERNAME $result" -body "Failures: $failureArray" -attachment $log
}
# --- Execution --- #
ForEach ($z in $primarys) {
$zone = $z.ZoneName
# auto created zones fail to export
If ($z.IsAutoCreated -eq $false -And $z.ZoneName -notLike "*arpa") {
Write-Host "Zone $zone" -ForegroundColor Green
$file = "$zone.dns.bak"
Write-Host "Exporting $zone to $file" -ForegroundColor Green
Try {
Export-DnsServerZone -Name $zone -FileName $file
} Catch {
Write-Warning "Failed to backup $zone"
$failureArray += $zone
Write-Host $_
}
$backupFile = $dnsRoot + $file
}
}
# zip-em and move-em
$zipFiles = "$dnsRoot\*.dns.bak"
Write-Host "Compressing archive $archive" -ForegroundColor Green
Compress-Archive -Path $zipFiles -DestinationPath $archive
Write-Host "Moving $archive to $backupLocation" -ForegroundColor Green
Try {
Move-Item -Path $archive -Destination $backupLocation
} Catch {
$failureArray += "move failure"
Write-Warning "move failure"
Write-Host $_
}
Try {
Remove-Item -Path "$dnsRoot\*.dns.bak" -Recurse
} Catch {
Write-Warning "failed to remove backup dir"
$failureArray += 'backup dir failed to remove'
Write-Host $_
}
# --- Ending Tasks --- #
mail
Note
This script utilizes my email script submodule.
Recovery
Start-Transcript 'C:\dns_recovery.log'
#Requires -RunAsAdministrator
Function dns_recovery {
param (
[Parameter(Mandatory=$True)]
[Object]$archive
)
# this cannot be changed, the commands will only load files from this dir
$dnsRoot = "C:\Windows\System32\dns"
If (!(Test-Path $archive)) {
Throw "$archive does not exist, check the path and try again"
}
Write-Host "Expanding $archive at $dnsRoot" -ForegroundColor Green
Expand-Archive -Path $archive -DestinationPath $dnsRoot
$allFiles = Get-ChildItem $dnsRoot
$backupFiles = $allFiles | Where {$_.Name -Like "*.dns.bak"}
ForEach ($file in $backupFiles) {
$zone = $file.Name.Replace('.dns.bak','')
Write-Host "Loading $zone from $file..." -ForegroundColor Green
Try {
Add-DnsServerPrimaryZone -ZoneName $zone -ZoneFile $file.Name -LoadExisting
} Catch {
Write-Warning "Failed to restore $zone"
}
}
Write-Host "Removing files from $dnsRoot"
Remove-Item -Path "$dnsRoot\*.dns.bak"
}
dns_recovery
Stop-Transcript
Notes
- The exported files are plaintext
- When exporting you can only specify a file name not location. The files can only go to
C:\Windows\System32\dns
and must be moved from there.
Updates: 2022-04-22: Added a check for arpa
specifically as it was an issue on my home DNS server.
References
Another basic script
An overview on the cmdlets and commands
Using PowerShell
- https://rietveld-ict.nl/dns-zone-recovery-using-powershell/
- https://stackoverflow.com/questions/65693302/how-do-you-create-a-new-microsoft-dns-zone-with-powershell-that-loads-from-a-dns
Docs on DNSServer Module