Dns Backups In Powershell
Tags: powershell, windows_dns, backups
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 GreenCompress-Archive -Path $zipFiles -DestinationPath $archive
Write-Host "Moving $archive to $backupLocation" -ForegroundColor GreenTry { 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